Сортировка списка файлов для загрузки по порядку

#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. Хорошо видимый ярлык.