Управление путями и каталогами с pathlib и os

В прошлой статье мы говорили об использовании модуля os для работы с каталогами в Python. Сегодня пойдёт речь о высокоуровневом Python-модуле pathlib. Читайте далее, чем отличаются os и pathlib, как управление путями зависит от операционной системы, а также что представляет собой работа с папками и файлами с помощью pathlib.

Иерархия pathlib

Архитектура pathlib состоит из чистых путей (pure path), которые имеют только вычислительные операции, но не имеют операций ввода-вывода, и конкретных путей (concrete path), которые наследуются от чистых путей, но также обладают операциями ввода-вывода. Рисунок ниже показывает иерархию наследования. Как можно заметить, левая часть (Posix Path) используется Unix-системами, а правая — MS Windows.

Диаграмма классов Path Python-модуля pathlib
Иерархия наследования Path

Если вы не знаете какой класс использовать, выбирайте Path. Его экземпляры будут подстраиваться под операционную систему (ОС), и во время выполнения вы получите конкретные экземпляры либо PosixPath, либо WindowsPath.
Чистые пути будут полезны в следующих случаях:

  1. Требуется управлять каталогами Windows в Unix-системах или наоборот. У вас не получится создать экземпляр WindowsPath в Unix, но можно воспользоваться PureWindowsPath.
  2. Требуется только управлять путями, не обращаясь к ОС. В этом случае создание экземпляра одного из чистых классов может быть полезным, поскольку у них просто нет операций доступа к ОС.

В дальнейшем мы покажем, как те же самые операции pathlib выполняются в модуле os. Так, pathlib предоставляет высокоуровневый интерфейс, а os — низкоуровенный, поэтому чаще возвращаемым значением является строка (str), а не объекты Path. Прежде чем приступим, импортируем модули в Python:

>>> from pathlib import Path
>>> import os

Текущая рабочая директория

Как мы уже говорили в прошлый раз файловая система и Python работают относительно текущей рабочей директории (current working directory). В pathlib для этого имеет метод cwd:

>>> os.getcwd()
'/home/user/Templates'
>>> pathlib.Path.cwd()
PosixPath('/home/user/Templates')

Ещё более короткий и удобный синтаксис вызова текущей директории – это передача в конструктор точку, а две точки укажут на родителя текущей директории:

>>> Path('.')
PosixPath('.') # текущая - '/home/user/Templates'
>>> Path('..')
PosixPath('..') # родитель - '/home/user/'

Создание путей

Разделитель используется для разделения папок в путях файловой системы. В os-модуле его можно посмотреть, вызвав os.sep. Но здесь возникают трудности, поскольку путь нужно сначала инициализировать в виде строки (str). А если вы забыли, что в Windows используется обратный слэш для деления папок вместо прямого, то код в этом месте придётся менять после вывода ошибки в Python-программе.
С другой стороны, интерфейс Python-модуля pathlib заставляет передавать путь в конструктор объекта Path, который уже сам решит во время выполнения, каким разделителем пользоваться:

>>> os.sep
'/'
>>> os.path.join('testfolder', 'sub-dir', 'example.txt')
'testfolder/sub-dir/example.txt'
>> Path('testfolder', 'sub-dir', 'example.txt')
PosixPath('testfolder/sub-dir/example.txt')
>>> p = Path('testfolder/sub-dir')

Чтобы добавить новые пути можно использовать слэш /, подобно арифметическому оператору, либо вызвать метод joinpath, причём соединять также можно и сами объекты Path:

>>> Path('.') / 'tempdir' / 'example.txt'
PosixPath('/home/user/Templates/tempdir/example.txt')
>>> p = Path('tempdir/examples.txt')
>>> Path.('.') / p
PosixPath('/home/user/Templates/tempdir/examples.txt')
# либо joinpath
>>> Path.('.').joinpath('tempdir', 'example.txt')
PosixPath('/home/user/Templates/tempdir/example.txt')

Информация о каталоге

В pathlib можно получить информацию о файле или папке, обращаясь к тем или иным атрибутам. Например, name для извлечения имени файла и его расширения, suffix для извлечения расширения файла. В Python это выглядит следующим образом:

# Информация о файле
>>> p = Path('tempdir/sub-dir/examples.txt')
>>> p.name
'examples.txt'
# Расширение файла
>>> p.suffix
'.txt'
# То же самое в os:
>>> os.path.basename(p)
'examples.txt'
>>> os.path.splitext(p)[1]
'.txt'

Гуляем по каталогу

У Path есть метод iterdir, который сгенерирует все папки и файлы указанного пути. Это очень полезно, когда, например, требуется выявить все файлы необходимого формата. Вот так в Python можно найти все текстовые файлы:

>>> p = Path('.')
>>> for file in p.iterdir():
...     if file.suffix == '.txt':
...         print(file.name)
...
example.txt
example2.txt

Ещё проще это можно сделать, используя метод glob, передав нужное расширение:

>>> for path in p.glob('*.txt'):
...     print(path)
...
example.txt
example2.txt

Чтобы пройтись также и по подпапкам в каталоге, можно воспользоваться методом rglob. В os для этого используется функция walk, о котором говорили тут. Ниже пример Python для вывода всех путей каталога, а также вывод файлов текстового формата всего каталога:

>>> p = Path('.')
>>> list(p.rglob('*'))
[PosixPath('example.txt'), PosixPath('sub-dir1'),
 PosixPath('example2.txt'), PosixPath('sub-dir2'),
 PosixPath('sub-dir2/example3.txt')]
>>> list(p.rglob('*.txt'))
[PosixPath('/home/user/Templates/example.txt')
 PosixPath('/home/user/Templates/example2.txt'),
 PosixPath('/home/user/Templates/sub-dir2/example3.txt')]

Работа с папками и файлами

Как и os, модуль pathlib даёт возможность создавать, удалять, переименовывать файлы и папки. Причём названия методов практически идентичные:

>>> Path('new-dir').mkdir() # создать папку
>>> Path('new-file').touch() # создать файл
>>> Path('super-dir').rmdir() # удалить папку
>>> Path('example.txt').unlink() # удалить файл
>>> Path('new-dir').rename('super-dir') # переименовать файл или папку
PosixPath('super-dir')

Кроме того, содержимое файла Path можно прочитать и записать. Ниже показан пример с записью и последующим чтением файла в Python.

>>> p = Path('exapmle.txt')
>>> p.write_text('Hello, python-school')
>>> p.read_text()
'Hello, python-school'

os или pathlib: что же всё-таки выбрать

После расcмотрения примеров возникает вопрос: каким Python-модулем пользоваться. Модуль os, помимо прочего, предоставляет множество функций для работы с процессами, пользователями, группами, окружением среды в Unix-системах. Но если вам требуется только интерфейс взаимодействия с файловой системой, стоит использовать pathlib, который будет отталкиваться от вашей ОС. При этом вам не потребуется помнить какой используется разделить в Windows или Unix-системах. Модуль pathlib прост в освоении, поскольку имеет простой синтаксис: нужно просто инициализировать объект Path, а дальше смотреть доступные методы. Кроме того, как уже говорилось в самом начале, многие функции os поддерживают объект Path в качестве аргумента, поэтому можно будет перейти от os к pathlib.
 
 
Еще больше подробностей о работе с файловой системой с помощью модуля pathlib на практических примерах реальных Data Science проектов вы узнаете на наших курсах по Python в лицензированном учебном центре обучения и повышения квалификации IT-специалистов в Москве.

Источники
  1. https://docs.python.org/3/library/pathlib.html

Добавить комментарий

Поиск по сайту