#python #python-3.x #sorting #os.walk
#python #python-3.x #сортировка #os.walk
Вопрос:
Моя цель — заставить python загружать файлы из заданного каталога в telegram, используя telegram-upload, в порядке возрастания. Кажется, что скрипт, который у меня есть, не может загружаться по порядку. Он загружает файлы в случайном порядке. Я использовал эту sorted
функцию безрезультатно. Глядя на мой скрипт, вы можете увидеть некоторые вещи, которые я пробовал (прокомментировал). У меня была настройка, в sorted
которой файлы перечислялись по порядку, но при попытке загрузки я не мог повторно преобразовать список, который я создал и отсортировал, обратно в строку, чтобы subprocess
можно было прочитать аргумент.
Вот сценарий:
import os
import subprocess
import time
#import shutil
Number_Of_Files = 0
#PATH = r'C:UsersmyuserDownloads'
PATH = '/home/pi/Public/'
for root, subFolder, files in os.walk(PATH):
for item in files:
#Number_Of_Files=Number_Of_Files 1
fileNamePath = os.path.join(root, item)
#sorted = sorted(fileNamePath)
#subprocess.run(['telegram-upload', '-f', 'my_channel', str(sorted)])
subprocess.run(['telegram-upload', '-f', 'my_channel', str(fileNamePath)])
#os.remove(fileNamePath)
print(fileNamePath)
#time.sleep(60)
#else:
#print(Number_Of_Files)
Комментарии:
1. вы сортируете
files
. я прав? если да, то это будетfor item in sorted(files):
2. Благодарим вас за включение прокомментированных версий кода, которые не работали. Так много новых программистов не могут показать, что они пробовали, и это очень расстраивает. Я ценю, что вы не заставляете меня догадываться, в чем проблема, и вместо этого предоставляете краткую, но полную информацию.
Ответ №1:
sorted
не работает на месте. subFolder
Аргумент должен быть отсортирован на месте, если вы хотите распространить изменения обратно os.walk
. Если вы хотите использовать files
напрямую, вам также необходимо отсортировать это на месте. В противном случае вам необходимо использовать отсортированную версию:
for root, subFolder, files in os.walk(PATH):
files.sort() # This sorts in-place
subFolder.sort() # If you want sorted directories
for item in files:
fileNamePath = os.path.join(root, item)
subprocess.run(['telegram-upload', '-f', 'my_channel', fileNamePath])
Если вы не хотите сортировать два списка на месте, вместо этого вы можете написать это так:
for root, subFolder, files in os.walk(PATH):
subFolder[:] = sorted(subFolder) # creates a new list and assigns back to the original
for item in sorted(files):
fileNamePath = os.path.join(root, item)
subprocess.run(['telegram-upload', '-f', 'my_channel', fileNamePath])
Бессмысленно бегать sorted
внутри вашего цикла. Поскольку sorted
каждый раз создается новый список, а цикл выполняется над исходным files
списком, ваш вызов sorted
не имеет никакого эффекта. Обычно вы хотите применить сортировку перед циклическим перебором последовательности, как я показал выше.
Комментарии:
1. Итак, я просто хотел сказать вам большое спасибо. Я добавил « files.sort(key= str.lower) # This сортирует вложенную папку на месте.sort() # Если вы хотите отсортировать каталоги « В свой код, и это сработало как шарм. Единственное изменение, которое мне пришлось внести, было
(key.str.lower)
связано с тем, что он хотел отсортировать A amp; a отдельно. Забавно, я ходил вокруг да около, но так и не увидел своей ошибки. Еще раз спасибо.
Ответ №2:
Весь ваш цикл может быть значительно упрощен с помощью pathlib и отсортирован:
import subprocess
from pathlib import Path
p=Path('/home/pi/Public/')
for fn in sorted((x for x in p.glob('**/*') if x.is_file())):
print(fn)
# subprocess.run(['telegram-upload', '-f', 'my_channel', str(fn)])
Это glob('**/*')
рекурсивный глобус, эквивалентный использованию os.walk
, но немного проще в управлении. Это (x for x in p.glob('**/*') if x.is_file())
понимание, которое возвращает только файлы, а не каталоги и файлы. Результат этого отсортирован, и вы уходите…
Учитывая эту структуру папок:
.
├── A
│ ├── b.txt
│ ├── d.txt
│ └── y.doc
└── B
├── a.txt
├── c.txt
└── x.doc
sorted((x for x in p.glob('**/*') if x.is_file())
возвращает файлы в этом порядке:
./A/b.txt
./A/d.txt
./A/y.doc
./B/a.txt
./B/c.txt
./B/x.doc
Если вы измените отсортированное понимание на sorted((x for x in p.glob('**/*') if x.is_file()), key=lambda x: x.name)
then, вы отсортируете это же дерево только по имени файла:
./B/a.txt
./A/b.txt
./B/c.txt
./A/d.txt
./B/x.doc
./A/y.doc
Или сначала отсортируйте по суффиксу, а затем назовите с помощью sorted((x for x in p.glob('**/*') if x.is_file()), key=lambda x: (x.suffix, x.name))
:
./B/x.doc
./A/y.doc
./B/a.txt
./A/b.txt
./B/c.txt
./A/d.txt
С помощью того же метода вы можете сортировать по времени создания, имени каталога, расширению и так далее…
Комментарии:
1. Спасибо за информацию. Я использовал исправление @Mad Physicist, и оно сработало как по волшебству. Тем не менее, я планирую использовать ваше предложение в другой итерации программы. Раньше мне не очень везло с glob, но вы вдохновили меня попробовать еще раз.
2. Хорошо видимый ярлык.