- Список файлов Python в каталоге и подкаталогах
- Как распечатать список файлов Python
- Список файлов в каталоге и подкаталогах с os.listdir()
- Получение списка файлов в каталоге и подкаталогах с помощью os.walk()
- Перечисление всех файлов txt в указанном каталоге с Glob в Python
- Список всех каталогов в указанном каталоге + подкаталоги(**)
- Заключение
- Функция os.walk
- Самая лучшая практика: работа с path в Python
- Объединяем пути с помощью Pathlib
- Обработка пути с помощью os.walk
- Лучшее решение с os.walk и Pathlib
Список файлов Python в каталоге и подкаталогах
В Python есть модуль ОС, предоставляющий функции для работы с файлами. Мы можем перечислить файлы в каталоге и подкаталоге программно в Python, используя модуль ОС. В этой статье мы обсудим различные методы создания списка всех файлов в дереве каталогов и подкаталогах..
Как распечатать список файлов Python
Давайте напечатаем все файлы, перечисленные в нашем текущем рабочем каталоге. Во-первых, вам нужно импортировать модуль os в свой файл, а затем использовать функцию os.listdir().
Напишите следующий код в файле app.py.
Список файлов в каталоге и подкаталогах с os.listdir()
Нам нужно рекурсивно вызвать функцию os.listdir() для подкаталогов, чтобы создать полный список файлов в заданном дереве каталогов.
В приведенном выше коде мы определили функцию с именем getFiles(), которая принимает один аргумент с именем dirname. Затем мы создаем список и добавляем полный путь к файлам.
Итак, он начнет перебирать один за другим файл и добавит его полный путь в список, и, в конце концов, мы получим наш полный список файлов.
Получение списка файлов в каталоге и подкаталогах с помощью os.walk()
Модуль python os предоставляет функцию walk() для перебора дерева каталогов.
Функция os.walk() перебирает дерево каталогов при указании пути и для каждого каталога или подкаталога возвращает кортеж, содержащий(, , ).
Перечисление всех файлов txt в указанном каталоге с Glob в Python
В приведенном выше примере мы использовали понимание списка, чтобы получить список всех файлов с расширением .txt.
Итак, в этом примере мы выводим только текстовые файлы, а не все файлы.
Список всех каталогов в указанном каталоге + подкаталоги(**)
Заключение
Чтобы вывести каталоги, подкаталоги и файлы, Python имеет отличную встроенную поддержку, которая делает всю работу за вас. Управление файлами и работа с ними — повседневная работа любого программиста.
В этой статье мы увидели, как перечислить все каталоги, подкаталоги и файлы, используя методы Python os.walk(), blob.blob() и Python os.listdir(). Наконец, Python перечисляет все файлы в каталоге, и пример с подкаталогами заканчивается.
Автор статей и разработчик, делюсь знаниями.
Функция os.walk
Функция walk модуля os принимает один обязательный аргумент и несколько необязательных. В качестве обязательного аргумента должен быть передан адрес каталога.
Функция walk() возвращает объект-генератор, из которого получают кортежи. Каждый кортеж «описывает» очередной каталог из переданного в функцию дерева каталогов.
Каждый кортеж состоит из трех элементов:
- Адрес очередного каталога в виде строки.
- Список имен подкаталогов первого уровня вложенности в данный каталог. Если вложенных каталогов нет, список будет пустым.
- Список имен файлов первого уровня вложенности в данный каталог. Если вложенных файлов нет, список будет пустым.
Допустим, есть такое дерево каталогов:
Передадим каталог test функции os.walk() :
import os tree = os.walk('test') print(tree) for i in tree: print(i)
('test', ['cgi-bin'], ['index.html', 'dgs.png']) ('test/cgi-bin', ['another', 'backup'], ['hello.py']) ('test/cgi-bin/another', [], ['data.txt']) ('test/cgi-bin/backup', [], [])
Если передать абсолютный адрес, адреса каталогов также будут абсолютными:
import os for i in os.walk('/home/pl/test'): print(i)
('/home/pl/test', ['cgi-bin'], ['index.html', 'dgs.png']) ('/home/pl/test/cgi-bin', ['another', 'backup'], ['hello.py']) ('/home/pl/test/cgi-bin/another', [], ['data.txt']) ('/home/pl/test/cgi-bin/backup', [], [])
Поскольку walk() возвращает генератор, повторно извлечь из него данные нельзя. Поэтому, если возникает необходимость сохранить кортежи, генератор можно «превратить» в список кортежей:
import os tree = list(os.walk('test')) for i in tree: print(i)
('test', ['cgi-bin'], ['index.html', 'dgs.png']) ('test/cgi-bin', ['another', 'backup'], ['hello.py']) ('test/cgi-bin/another', [], ['data.txt']) ('test/cgi-bin/backup', [], [])
Чтобы получить полный адрес файла (абсолютный или относительный), следует воспользоваться функцией os.path.join :
import os.path for address, dirs, files in os.walk('test'): for name in files: print(os.path.join(address, name))
test/index.html test/dgs.png test/cgi-bin/hello.py test/cgi-bin/another/data.txt
Переменная address на каждой итерации связывается с первым элементом очередного кортежа (строкой, содержащей адрес каталога), dirs – со вторым элементом (списком подкаталогов), а files — со списком файлов этого каталога. Во вложенном цикле извлекается имя каждого файла из списка файлов.
У функции walk есть аргумент topdown , который по умолчанию имеет значение True . Если ему присвоить False , то обход дерева каталогов будет происходить не «сверху вниз» (от корневого к вложенным), а наоборот — «снизу вверх» (первыми будут подкаталоги).
import os tree = os.walk('test', topdown=False) for i in tree: print(i)
('test/cgi-bin/another', [], ['data.txt']) ('test/cgi-bin/backup', [], []) ('test/cgi-bin', ['another', 'backup'], ['hello.py']) ('test', ['cgi-bin'], ['index.html', 'dgs.png'])
Самая лучшая практика: работа с path в Python
В последней статье мы использовали рекурсивную функцию размером менее 10 строк для решения проблемы сканирования папок и ранжирования файлов по дате изменения и размеру.
Теперь я подниму планку и покажу, как можно было сделать лучше.
Объединяем пути с помощью Pathlib
Старые идеи в новом обличье?
Предыдущее решение с соединением путей выглядело следующим образом:
path_file = os.sep.join([path_dir, filename])
Преимущество такого подхода заключается в том, что решение не зависит от операционной системы, и вам не нужно складывать строки с помощью оператора «+» или форматирования.
Тем не менее, здесь можно допустить ошибку, например, непреднамеренно или ошибочно определить путь к каталогу с помощью закрывающего разделителя.
path_dir: str = r"C:/Users/sselt/Documents/blog_demo/" # abschließender Trenner filename: str = "some_file" path_file = os.sep.join([path_dir, filename]) # C:/Users/sselt/Documents/blog_demo/\some_file
Несмотря на то, что в этом примере показан рабочий код, неправильный разделитель приведет к ошибке при вызове этого пути. И такие ошибки могут возникать всякий раз, когда далекие от кода пользователи оперируют путями в конфигурационных файлах, не обращая внимания на соглашения.
В Python 3.4 появилось лучшее решение — модуль pathlib . Он обрабатывает функции файлов и папок модуля os с помощью объектно-ориентированного подхода.
Напомню, старый вариант выглядел вот так:
import os path = "C:/Users/sselt/Documents/blog_demo/" os.path.isdir(path) os.path.isfile(path) os.path.getsize(path)
from pathlib import Path path: Path = Path("C:/Users/sselt/Documents/blog_demo/") path.is_dir() path.is_file() path.stat().st_size
Оба варианта дают один и тот же результат. Так чем же второй вариант лучше?
Объектно-ориентированный и более устойчивый к ошибкам
Вызовы в основном являются объектно-ориентированными, нравится вам это или нет, но лично мне такой подход по душе. Здесь у нас есть такой объект, как определение path , у которого есть атрибуты и методы.
Однако пример с операторами перегрузки в данном случае более интересен:
filename: Path = Path("some_file.txt") path: Path = Path("C:/Users/sselt/Documents/blog_demo") print( path / filename ) # C:\Users\sselt\Documents\blog_demo\some_file.txt
Сначала разделение на два пути кажется недопустимым. Однако объект path был перегружен так, чтобы работать как объединенный путь.
В дополнение к этому синтаксическому сахару объекты path будут перехватывать другие типичные ошибки:
filename: Path = Path("some_file.txt") # hier path mit überflüssigem Trenner am Schluss path: Path = Path("C:/Users/sselt/Documents/blog_demo/") # hier path mit doppeltem Trenner path: Path = Path("C:/Users/sselt/Documents/blog_demo//") # hier path völlig durcheinander path: Path = Path("C:\\Users/sselt\\Documents/blog_demo") # hier ein wilder Mix # alle Varianten führen zum selben Ergebnis print(path/filename) # C:\Users\sselt\Documents\blog_demo\some_file.txt
Такой вариант не только приятнее, но и устойчивее к неправильным входным данным. В дополнение к другим преимуществам код также не привязан к определенной операционной системе. Он определяет только generic объект path , который объявляется в системе Windows как WindowsPath , а в Linux как PosixPath .
Большинство функций, которые ожидают строку в качестве пути, могу работать непосредственно с путем. В редких случаях вам может понадобиться изменить объект просто с помощью str(Path) .
Обработка пути с помощью os.walk
В своей последней статье я использовал os.listdir , os.path.isdir и рекурсивную функцию для итерации по дереву путей и разграничения файлов и папок.
Но os.walk предлагает решение получше. Этот метод создает не список, а итератор, который можно вызывать построчно. В результате мы получим соответствующий путь к папке и список всех файлов по этому пути. Весь процесс происходит рекурсивно, поэтому вы получите все файлы одним вызовом.
Лучшее решение с os.walk и Pathlib
Если вы объедините два вышеупомянутых метода, то получите решение, которое будет более простым, полностью независимым от операционной системы, устойчивым к неправильным форматам путей и без явных рекурсий:
filesurvey = [] for row in os.walk(path): # row beinhaltet jeweils einen Ordnerinhalt for filename in row[2]: # row[2] ist ein tupel aus Dateinamen full_path: Path = Path(row[0]) / Path(filename) # row[0] ist der Ordnerpfad filesurvey.append([path, filename, full_path.stat().st_mtime, full_path.stat().st_size])
Если вам удастся улучшить этот вариант, не постесняйтесь рассказать мне об этом. Я был бы рад вашим отзывам!
Первую часть статьи можно найти здесь.
Перевод статьи подготовлен в преддверии старта курса «Python Developer. Basic».
Также приглашаем всех желающих принять участие в бесплатном демо-уроке курса на тему «Три кита: map(), filter() и zip()».
Можно ли писать код, требующий циклов, но без циклов? Может ли он быть быстрее, чем, если бы мы использовали циклы в Python? Для реализации задуманного понадобится знание слов «callback», «iterator» и «lambda». Если интересно — присоединяйтесь!