Автор выбрал COVID-19 Relief Fund для получения пожертвования в рамках программы Write for DOnations.
Введение
Python 3 включает модуль pathlib
для манипуляции путями файловых систем независимо от операционной системы. pathlib
похож на модуль os.path
, но pathlib
предлагает более развитый и удобный интерфейс по сравнению с os.path
.
Мы можем идентифицировать файлы на компьютере с помощью иерархических путей. Например, мы можем идентифицировать файл wave.txt
на компьютере с помощью этого пути: /Users/sammy/ocean/wave.txt
. Операционные системы представляют пути несколько по-разному. Windows может представлять путь к файлу wave.txt
как C:Userssammyoceanwave.txt
.
Модуль pathlib
может быть полезен, если в программе Python вы создаете или перемещаете файлы в файловой системе, указывая все файлы в файловой системе, совпадающие с данным расширением или шаблоном, или создаете пути файла, соответствующие файловой системе на основе наборов неформатированных строк. Хотя вы можете использовать другие инструменты, например модуль os.path
, для выполнения большей части этих задач, модуль pathlib
позволяет выполнять эти операции с большей степенью читаемости и минимальным количеством кодов.
В этом обучающем модуле мы рассмотрим некоторые способы использования модуля pathlib
для представления и манипуляции путями файловых систем.
Предварительные требования
Чтобы получить максимум знаний из этого обучающего модуля, рекомендуется иметь небольшое представление о программировании на Python 3. Дополнительную информацию можно найти в следующих обучающих руководствах:
Построение экземпляров Path
Модуль pathlib
предоставляет несколько классов, но одним из наиболее важных является класс Path
. Экземпляры класса Path
представляют путь к файлу или каталогу в файловой системе вашего компьютера.
Например, следующий код инстанциирует экземпляр Path
, который представляет часть пути к файлу wave.txt
:
from pathlib import Path
wave = Path("ocean", "wave.txt")
print(wave)
Если запустить этот код, результат будет выглядеть следующим образом:
Output
ocean/wave.txt
from pathlib import Path
делает класс Path
доступным для нашей программы. Затем Path("ocean", "wave.txt")
инстанциирует новый экземпляр Path
. Вывод отображает, что Python добавил соответствующий разделитель оперативной системы /
между двумя заданными нами компонентами пути "ocean"
и "wave.txt"
.
Примечание. В зависимости от операционной системы вывод может немного отличаться от примеров, приведенных в данном руководстве. Если вы работаете в Windows, например, ваш вывод для этого первого примера может выглядеть как oceanwave.txt
.
В настоящее время объект Path
, назначенный на переменную wave
, содержит относительный путь. Другими словами, ocean/wave.txt
может существовать в нескольких местах в нашей файловой системе. В качестве примера он может существовать в /Users/user_1/ocean/wave.txt
или /Users/user_2/research/ocean/wave.txt
, но мы не указали к какому из них конкретно мы обращаемся. Абсолютный путь, напротив, однозначно четко указывает на расположение в файловой системе.
Вы можете использовать Path.home()
для получения абсолютного пути к домашнему каталогу текущего пользователя:
home = Path.home()
wave_absolute = Path(home, "ocean", "wave.txt")
print(home)
print(wave_absolute)
Если запустить этот код, результат будет выглядеть приблизительно следующим образом:
Output
/Users/sammy
/Users/sammy/ocean/wave.txt
Примечание. Как упоминалось ранее, вывод будет зависеть от операционной системы. Ваш домашний каталог также будет отличаться от /Users/sammy
.
Path.home()
возвращает экземпляр Path
с абсолютным путем в домашний каталог текущего пользователя. Затем мы передадим этот экземпляр Path
и строки "ocean"
и "wave.txt"
в другой конструктор Path
, чтобы создать абсолютный путь к файлу wave.txt
. Вывод показывает, что первая строка — это домашний каталог, а вторая строка — домашний каталог плюс ocean/wave.txt
.
Этот пример также иллюстрирует важную функцию класса Path
: конструктор Path
принимает обе строки и ранее существовавшие объекты Path
.
Давайте более детально рассмотрим поддержку строк и объектов Path
в конструкторе Path
:
shark = Path(Path.home(), "ocean", "animals", Path("fish", "shark.txt"))
print(shark)
Если запустить этот код Python, результат будет выглядеть следующим образом:
Output
/Users/sammy/ocean/animals/fish/shark.txt
shark
— это Path
к файлу, который мы создали с помощью объектов Path
(Path.home()
и Path("fish", "shark.txt")
и строк "ocean"
и "animals"
). Конструктор Path
интеллектуально обрабатывает оба типа объектов и аккуратно соединяет их с помощью соответствующего разделителя операционной системы, в данном случае /
.
Доступ к атрибутам файла
Теперь, когда мы узнали, как создать экземпляры Path
, давайте рассмотрим, как можно использовать эти экземпляры для доступа к информации о файле.
Мы можем использовать атрибуты name
и suffix
для доступа к именам и расширениям файлов:
wave = Path("ocean", "wave.txt")
print(wave)
print(wave.name)
print(wave.suffix)
Запустив этот код, мы получим вывод, аналогичный следующему:
Output
/Users/sammy/ocean/wave.txt
wave.txt
.txt
Этот вывод показывает, что имя файла в конце нашего пути — wave.txt
, а расширение файла — .txt
.
Экземпляры Path
также предлагают функцию with_name
, позволяющую беспрепятственно создавать новый объект Path
с другим именем:
wave = Path("ocean", "wave.txt")
tides = wave.with_name("tides.txt")
print(wave)
print(tides)
Если запустить его, результат будет выглядеть следующим образом:
ocean/wave.txt
ocean/tides.txt
Код сначала создает экземпляр Path
, указывающий на файл с именем wave.txt
. Затем мы вызовем метод with_name
в wave
, чтобы вернуть второй экземпляр Path
, указывающий на новый файл с именем tides.txt
. Часть каталога ocean/
остается неизмененной и оставляет финальный путь в виде ocean/tides.txt
Доступ к предшествующим объектам
Иногда полезно получить доступ к каталогам, содержащим определенный путь. Давайте рассмотрим пример:
shark = Path("ocean", "animals", "fish", "shark.txt")
print(shark)
print(shark.parent)
Если запустить этот код, результат будет выглядеть следующим образом:
Output
ocean/animals/fish/shark.txt
ocean/animals/fish
Атрибут parent
в экземпляре Path
возвращает ближайшего предшественника пути данного файла. В этом случае он возвращает каталог с файлом shark.txt
: ocean/animals/fish
.
Мы можем получать доступ к атрибуту parent
несколько раз в строке, чтобы пройти вверх по корневому дереву данного файла:
shark = Path("ocean", "animals", "fish", "shark.txt")
print(shark)
print(shark.parent.parent)
Если мы выполним этот код, мы увидим следующие результаты:
Output
ocean/animals/fish/shark.txt
ocean/animals
Вывод будет похож на предыдущий вывод, но теперь мы перешли на уровень выше, получив доступ к .parent
во второй раз. Два каталога от shark.txt
— это каталог ocean/animals
.
Использование шаблона поиска для списка файлов
Также можно использовать класс Path
для списка файлов с помощью метода glob
.
Допустим, у нас есть структура каталога, которая выглядит следующим образом:
└── ocean
├── animals
│ └── fish
│ └── shark.txt
├── tides.txt
└── wave.txt
Каталог ocean
содержит файлы tides.txt
и wave.txt
. У нас есть файл с именем shark.txt
, вложенный в каталог ocean
, каталог animals
и каталог fish
: ocean/animals/fish
.
Чтобы перечислить все файлы .txt
в каталоге ocean
, можно сказать:
for txt_path in Path("ocean").glob("*.txt"):
print(txt_path)
Этот код произведет следующий вывод:
Output
ocean/wave.txt
ocean/tides.txt
Шаблон поиска "*.txt"
находит все файлы, заканчивающиеся на .txt
. Поскольку пример кода выполняет этот поиск в каталоге ocean
, он возвращает два файла .txt
в каталоге ocean
: wave.txt
и tides.txt
.
Примечание. Если вы хотите дублировать выводы, указанные в данном примере, вам потребуется имитировать структуру каталога, изображенную здесь, на компьютере.
Также мы можем использовать метод glob
рекурсивно. Чтобы перечислить все файлы .txt
в каталоге ocean
и все его подкаталоги, мы можем сказать:
for txt_path in Path("ocean").glob("**/*.txt"):
print(txt_path)
Если запустить этот код, результат будет выглядеть следующим образом:
Output
ocean/wave.txt
ocean/tides.txt
ocean/animals/fish/shark.txt
Часть **
шаблона поиска будет соответствовать этому каталогу и всем каталогам под ним рекурсивно. Поэтому в выводе у нас будут не только файлы wave.txt
и tides.txt
, но также мы получим файл shark.txt
, вложенный в ocean/animals/fish
.
Вычисление относительных путей
Мы можем использовать метод Path.relative_to
для вычисления путей, относящихся друг к другу. Метод relative_to
полезен, если, например, вы хотите получить часть длинного пути файла.
Рассмотрите следующий код:
shark = Path("ocean", "animals", "fish", "shark.txt")
below_ocean = shark.relative_to(Path("ocean"))
below_animals = shark.relative_to(Path("ocean", "animals"))
print(shark)
print(below_ocean)
print(below_animals)
Если запустить его, результат будет выглядеть следующим образом:
Output
ocean/animals/fish/shark.txt
animals/fish/shark.txt
fish/shark.txt
Метод relative_to
возвращает новый объект Path
, относящийся к данному аргументу. В нашем примере мы вычислим Path
к shark.txt
, относящийся к каталогу ocean
, а затем относящийся к обоим каталогам ocean
и animals
.
Если relative_to
не сможет вычислить ответ, поскольку мы даем ему не связанный путь, он выдаст ValueError
:
shark = Path("ocean", "animals", "fish", "shark.txt")
shark.relative_to(Path("unrelated", "path"))
Мы получим исключение ValueError
, возникшее из этого кода, которое будет выглядеть следующим образом:
Output
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/Python3.8/pathlib.py", line 899, in relative_to
raise ValueError("{!r} does not start with {!r}"
ValueError: 'ocean/animals/fish/shark.txt' does not start with 'unrelated/path'
unrelated/path
не является частью ocean/animals/fish/shark.txt
, поэтому Python не сможет вычислить относительный путь.
Заключение
Модуль pathlib
— это мощная часть стандартной библиотеки Python, которая позволяет нам быстро манипулировать путями файловых систем в любой операционной системе. В этом обучающем модуле мы научились использовать некоторые ключевые утилиты pathlib
для доступа к атрибутам файла, спискам файлов с помощью шаблонов поиска и переходить к родительским файлам и каталогам.
Модуль pathlib
представляет дополнительные классы и утилиты, которые мы не охватили в данном руководстве. После получения базового уровня вы можете использовать документацию модуля pathlib
для получения дополнительной информации о других имеющихся классов и утилитах.
Если вас интересуют другие библиотеки Python, ознакомьтесь со следующими обучающими модулями: