Управление путями к файлам с помощью Python – это целая история!
Python отлично подходит для создания программ, управляющих файлами и папками. Лично у меня на компьютере каждый день выполняется добрый десяток скриптов для различных задач систематизации и организации операционной системы.
Исторически мы использовали такие модули, как os, glob или shutil для выполнения операций создания, удаления и управления файлами.
Модуль pathlib, доступный с версии 3.4 Python, позволяет выполнять почти все распространенные операции над операционной системой, причем объектно-ориентированный синтаксис гораздо приятнее в использовании.
Содержание
Класс Path
Класс Path позволяет создать объект, представляющий путь к файлу или папке на нашем компьютере.
Этот путь может существовать или не существовать на нашем жестком диске, это не является обязательным условием.
Path имеет несколько методов класса, позволяющих получить доступ к общим путям нашей операционной системы, например, к папке пользователя :
from pathlib import Path
user_folder = Path.home()
Code language: JavaScript (javascript)
Можно также получить текущую папку:
from pathlib import Path
current_folder = Path.cwd()
Code language: JavaScript (javascript)
Или создать конкретный путь, передав строку классу Path:
from pathlib import Path
documents = Path("/Users/user/Documents")
Code language: JavaScript (javascript)
Примечание. Если мы отобразим объект, созданный на основе класса Path, то в итоге получим объект PosixPath. Этот объект представляет пути систем Linux и Mac OS. В Windows объект будет другим, потому что пути в Windows не такие, как в Mac и Linux. Это не изменяет методы и атрибуты, которые могут быть использованы для этого объекта.
>>> from pathlib import Path
>>> documents = Path("/Users/user/Documents")
>>> print(documents)
PosixPath('/Users/user/Documents')
Code language: JavaScript (javascript)
Конкатенация путей
Чтобы объединить пути, очень просто, достаточно использовать косую черту:
from pathlib import Path
home = Path.home() # PosixPath('/Users/user/')
documents = home / "Documents" # PosixPath('/Users/user/Documents')
Code language: PHP (php)
Результат этой конкатенации возвращает новый объект PosixPath, поэтому мы можем объединить несколько строк подряд.
Примечание. pathlib работает с различными операционными системами и использует косую или обратную косую черту в зависимости от того, используете ли вы Mac/Linux или Windows. Это поведение похоже на функцию os.path.join модуля os.
from pathlib import Path
home = Path.home() # PosixPath('/Users/user/')
documents = home / "Documents" / "Project" # PosixPath('/Users/user/Documents/Project')
Code language: PHP (php)
Вы также можете использовать метод joinpath для объекта Path. Это может быть полезно, если у вас есть, например, список папок, которые вы хотите объединить (благодаря распаковке и оператору splat *):
from pathlib import Path
home = Path.home() # PosixPath('/Users/user/')
files = ['Projects', 'Django', 'blog']
home.joinpath(*files) # PosixPath('/Users/user/Projects/Django/blog')
Code language: PHP (php)
Если вы используете косые черты и хотите использовать метод объекта Path, не забывайте использовать круглые скобки для заключения конкатенированных путей:
from pathlib import Path
home = Path.home() # PosixPath('/Users/user/')
# Не сработает, потому что мы пытаемся получить атрибут суффикса строки "main.py".
home / "Projcet" / "main.py".suffix
# Со скобками это работает!
(home / "Project" / "main.py").suffix
Code language: PHP (php)
Получение информации о пути
Благодаря объектно-ориентированному подходу, мы можем получить доступ ко многим сведениям о пути с помощью атрибутов объекта Path:
from pathlib import Path
p = Path("/Users/user/Documents/index.html")
p.name # "index.html"
p.parent # "/Users/user/Documents"
p.stem # "index"
p.suffix # ".html"
p.parts # ("/", "Users", "user", "documents", "index.html")
Code language: PHP (php)
Существуют также методы проверки существования и типа пути:
from pathlib import Path
p = Path("/Users/user/Documents/index.html")
p.exists() # True
p.is_dir() # False
p.is_file() # True
Code language: PHP (php)
И снова, когда путь может быть возвращен одним из этих атрибутов, мы получаем объект Path.
Поэтому мы можем несколько раз поместить один и тот же атрибут в конец, чтобы, например, подняться из нескольких папок:
from pathlib import Path
p = Path("/Users/user/Documents/index.html")
p.parent.parent # "/Users/user"
Code language: PHP (php)
Создание и удаление папок
Чтобы создать папку, можно использовать метод mkdir. Этот метод будет работать по умолчанию, только если папка не существует.
Вы можете использовать параметр exist_ok, чтобы указать, что вы не хотите, чтобы выдавалась ошибка, если папка уже существует:
from pathlib import Path
file = Path("/Users/user/Documents/SiteWeb")
file.mkdir() # Вызывает ошибку, если файл уже существует
file.mkdir(exist_ok=True)
Code language: PHP (php)
Если вы хотите создать несуществующую иерархию папок, необходимо добавить параметр parent :
from pathlib import Path
# Папка SiteWeb и ее вложенные папки не существуют
file = Path("/Users/user/Documents/SiteWeb/sources/css")
# Вы можете создать все разом с помощью параметра parent
file.mkdir(parents=True)
Code language: PHP (php)
Чтобы удалить папку, используйте метод rmdir:
from pathlib import Path
file = Path("/Users/user/Documents/SiteWeb")
file.rmdir()
Code language: JavaScript (javascript)
Этот метод работает только в том случае, если папка пуста.
Если папка содержит файлы или другие вложенные папки, этот метод не работает, и это единственный случай, когда нам придется вернуться к модулю shutil и функции rmtree:
import shutil
from pathlib import Path
file = Path("/Users/user/Documents/SiteWeb")
shutil.rmtree(file)
Code language: JavaScript (javascript)
Создание, чтение и запись в файл
Для создания и удаления файла можно использовать методы touch и unlink соответственно:
from pathlib import Path
file = Path("/Users/user/Documents/SiteWeb/index.html")
file.touch()
file.unlink()
Code language: JavaScript (javascript)
Для записи содержимого в файл мы используем метод write_text:
from pathlib import Path
file = Path("/Users/user/Documents/SiteWeb/index.html")
file.write_text("Главная страница")
Code language: JavaScript (javascript)
При использовании метода touch не обязательно предварительно создавать файл.
Согласитесь, что это быстрее, чем делать :
from pathlib import Path
file = Path("/Users/user/Documents/SiteWeb/index.html")
with open(file, "w") as f:
f.write("Главная страница")
Code language: JavaScript (javascript)
Таким же образом для чтения содержимого файла мы можем использовать метод read_text:
>>> from pathlib import Path
>>> file = Path("/Users/user/Documents/SiteWeb/index.html")
>>> file.read_text()
"Главная страница"
Code language: JavaScript (javascript)
Сканирование папки
Где pathlib действительно потрясает, так это в способности сканировать папки вашего компьютера с помощью методов, которые гораздо легче запомнить, чем модуль glob.
Чтобы получить все файлы и папки внутри папки, можно использовать метод iterdir:
from pathlib import Path
for f in Path.home().iterdir():
print(f.name)
Code language: CSS (css)
Этот метод можно комбинировать с методом is_dir для получения только папок (здесь с помощью понимания списка):
from pathlib import Path
files = [d for d in Path.home().iterdir() if d.is_dir()]
Code language: JavaScript (javascript)
Для более гибкого сканирования папки можно использовать метод glob. Например, вы можете получить только файлы с расширением .png:
from pathlib import Path
for f in Path.home().glob("*.png"):
print(f.name)
Code language: CSS (css)
Если вы хотите сканировать папку рекурсивно, просто используйте rglob вместо glob :
from pathlib import Path
for f in Path.home().rglob("*.png"):
print(f.name)
Code language: CSS (css)
Несколько практических примеров
Вот несколько практических примеров того, насколько гибким и простым является использование pathlib.
Добавление суффикса к имени файла
from pathlib import Path
p = Path.home() / "image.png" # "/Users/user/image.png"
p.parent / (p.stem + "-lowres" + p.suffix) # "/Users/user/image-lowres.png"
Code language: PHP (php)
Сортировка файлов по расширению
from pathlib import Path
dirs = {".jpg": "Images",
".gif": "Images",
".mp4": "Videos",
".pdf": "Documents",
".mp3": "Music",
".wav": "Music"}
sort_dir = Path.home() / "Сортировка"
files = [f for f in tri_dir.iterdirs() if f.is_file()]
for f in files:
# Если для расширения не найдено соответствия, файлы помещаются в папку Others
output_dir = sort_dir / dirs.get(f.suffix, "Others")
output_dir.mkdir(exist_ok=True)
f.rename(output_dir / f.name)
Code language: PHP (php)
Для перемещения файла можно использовать метод rename.
Создание константы папки с помощью __file__
from pathlib import Path
SOURCE_FILE = Path(__file__).resolve() # resolve позволяет разрешать символические ссылки
SOURCE_DIR = SOURCE_FILE.parent
ROOT_DIR = SOURCE_FILE.parent
DATA_DIR = SOURCE_DIR / "DATA"
Code language: PHP (php)
Заключение
Я надеюсь, что после этой статьи вы сможете увидеть преимущество использования pathlib для всего, что связано с управлением файлами и папками в вашей операционной системе.
По-прежнему важно знать модули os, shutil и glob, поскольку в интернете можно найти множество скриптов, использующих их. Но если вы начинаете новый проект с Python 3.4+, то не сомневайтесь ни секунды!