import Path # Новое в Python 3.12. dirpath, dirnames, filenames = Path.walk(top_down=True, on_error=None, follow_symlinks=False)
top_down=True
- определяет направление перебора дерева каталогов либо сверху вниз, либо снизу вверх;on_error=None
- вызываемый объект, принимающий экземпляр OSError
;follow_symlinks=False
- переходить ли по символическим ссылкам.(dirpath, dirnames, filenames)
Метод Path.walk()
модуля pathlib
генерирует имена файлов в дереве каталогов, перемещаясь по дереву либо сверху вниз, либо снизу вверх.
Для каждого каталога, корнем которого является self
(включая self
, но исключая ‘.’
и ‘..’
) метод возвращает кортеж из трех элементов (dirpath, dirnames, filenames)
:
dirpath
- это путь к каталогу, который в данный момент просматривается, dirnames
- это список строк для имен подкаталогов в dirpath
(исключая '.' и '..'), filenames
- это список строк для имен файлов, не относящихся к каталогу, в dirpath
. Чтобы получить полный путь (который начинается с self
) к файлу или каталогу в dirpath
, нужно выполнить команду dirpath / name
. Сортируются списки или нет, зависит от файловой системы.
Если необязательный аргумент top_down
имеет значение True
(по умолчанию), то кортежи (dirpath, dirnames, filenames)
для каталога генерируется раньше кортежей для любого из его подкаталогов (т.е. каталоги просматриваются сверху вниз). Если top_down
имеет значение False
, то кортежи (dirpath, dirnames, filenames)
для каталога генерируется после кортежей для всех его подкаталогов (т.е. каталоги просматриваются снизу вверх). Независимо от значения top_down
, список подкаталогов извлекается до того, как будут пройдены кортежи каталога и его подкаталогов.
Когда top_down
имеет значение True
, вызывающая сторона может изменять список имен каталогов dirnames
на месте (например, используя del или срез), а Path.walk()
будет рекурсивно обращаться только к подкаталогам, имена которых остаются в dirnames
. Такое поведение можно использовать для сокращения поиска, или для установления определенного порядка посещения, или даже для информирования Path.walk()
о каталогах, которые вызывающий объект создает или переименовывает, прежде чем метод снова возобновит обход. Изменение dirnames
, когда top_down=False
не влияет на поведение Path.walk()
, т. к. каталоги в dirnames
уже созданы к моменту, когда dirnames
передаются вызывающему объекту.
По умолчанию ошибки os.scandir()
игнорируются. Если указан необязательный аргумент on_error
, то он должен быть вызываемым объектом, принимающим один аргумент - экземпляр OSError
. Этот вызываемый объект может обработать ошибку, чтобы продолжить обход, или повторно поднять исключение, чтобы остановить обход. Обратите внимание, что имя файла доступно как атрибут filename
объекта exception
.
В примере ниже считается количество байт, занятое файлами в каждом каталоге, при этом игнорируются каталоги __pycache__
:
from pathlib import Path concurrent = Path("cpython/Lib/concurrent") for root, dirs, files in concurrent.walk(on_error=print): print( root, "содержит", sum((root / file).stat().st_size for file in files), "байт в", len(files), "файлах, не относящиеся к каталогу" ) if '__pycache__' in dirs: dirs.remove('__pycache__')
По умолчанию Path.walk()
не следует по символическим ссылкам, а только добавляет их в список filenames
. Чтобы разрешать символические ссылки и размещать их в dirnames
и filenames
в соответствии с их целями и, следовательно, посещать каталоги, на которые указывают символические ссылки (там, где это поддерживается), необходимо установить follow_symlinks=True
.
Важно!. Нужно понимать, что установка
follow_symlinks=True
может привести к бесконечной рекурсии, если ссылка указывает на собственный родительский каталог. МетодPath.walk()
не отслеживает каталоги, которые он уже посетил.Примечание. Метод
Path.walk()
предполагает, что каталоги, по которым он проходит, не изменяются во время выполнения. Например, если каталог изdirnames
был заменен символической ссылкой, аfollow_symlinks=False
, тоPath.walk()
все равно попытается спуститься в него. Чтобы предотвратить такое поведение, нужно удалить измененные каталоги изdirnames
, если это необходимо.Примечание. В отличие от
os.walk()
, Path.walk() перечисляет символические ссылки на каталоги вfilenames
, если значениеfollow_symlinks=False
.
Path.walk()
.Пример представляет собой простую реализацию shutil.rmtree()
. Обход дерева снизу вверх очень важен, поскольку Path.rmdir()
не позволяет удалить каталог, пока он не станет пустым.
ОСТОРОЖНО: Это опасно! Например, если
delete == Path('/')
, то запуск примера может привести к удалению всех файлов.
from pathlib import Path # удаляет все, что доступно из каталога 'delete_dir'. delete = Path('delete_dir') for root, dirs, files in delete.walk(top_down=False): for name in files: (root / name).unlink() for name in dirs: (root / name).rmdir()