Как получить текущую директорию в Python

Многие программы на Python нуждаются в навигации по файловой системе для чтения и записи файлов. При этом частой операцией является получение текущего каталога.

Текущую рабочую директорию или каталог сокращенно называют CWD — от англ. «current working directory».

В Python есть два основных модуля, которые можно использовать для доступа к путям файловой системы: модуль os и модуль pathlib.

Модуль os предлагает традиционный подход к получению текущей рабочей директории и работает с путями и файловой системой.

Модуль pathlib — это более новый модуль, который предлагает объектно-ориентированный подход, надежный и кроссплатформенный.

В этой статье мы рассмотрим различные методы получения текущей рабочей директории и работы с ней.

Как получить текущую рабочую директорию

Текущая рабочая директория — это папка, в которой выполняется программа на Python. Она служит точкой отсчета для относительных путей к файлам.

Давайте рассмотрим, как получить доступ к текущей рабочей директории с помощью модулей os и pathlib, и сравним эти два решения.

Использование os.getcwd()

Модуль os позволяет получить доступ к операционной системе компьютера. Функция getcwd() определяет текущий рабочий каталог:

import os
cwd = os.getcwd()
print(cwd)

# Результат:
# /Users/sg/Documents/GitHub/datacamp

На выходе вы увидите путь к директории, содержащей скрипт. Формат пути зависит от операционной системы. Приведенный выше вывод относится к операционным системам POSIX, таким как Linux, Unix и macOS.

Тот же путь в системе Windows будет выглядеть следующим образом:

C:\Users\sg\Documents\GitHub\datacamp

Значение, возвращаемое os.getcwd(), представляет собой строку:

print(type(cwd))

# Результат:
# <class 'str'>

Поэтому для работы с этим путем нам нужно использовать строковые методы и другие строковые операции.

Использование pathlib.Path.cwd()

В Python 3.4 появился модуль pathlib, который предлагает объектно-ориентированный подход к доступу и манипулированию путями к файлам. Основным классом в pathlib является Path, который мы можем импортировать перед получением текущей рабочей директории:

from pathlib import Path
cwd = Path.cwd()
print(cwd)

# Результат:
# /Users/sg/Documents/GitHub/datacamp

Вывод Path.cwd() похож на значение, возвращаемое os.getcwd(). Но Path.cwd() возвращает не строку. Мы можем убедиться в этом, распечатав тип возвращаемого объекта или выведя его официальное строковое представление с помощью repr():

print(type(cwd))
print(repr(cwd))

# Результат:
# <class 'pathlib.PosixPath'>
# PosixPath('/Users/sg/Documents/GitHub/datacamp')

На компьютере под управлением Windows функция Path.cwd() возвращает объект WindowsPath.

Объекты PosixPath и WindowsPath предоставляют схожую функциональность, позволяя создавать кроссплатформенные программы. Вот некоторые из атрибутов этих объектов:

print(cwd.parent)
print(cwd.name)

# Результат:
# /Users/sg/Documents/GitHub
# datacamp

По возможности лучше использовать модуль pathlib: он более современный и упрощает работу с путями.

Работа с текущей директорией

В программах на Python часто возникает необходимость манипулировать путем, например, чтобы сохранить файл во вложенной папке. Предположим, нам нужно создать новый подкаталог в текущей рабочей директории и сохранить в нем текстовый файл.

Использование модуля os

Функция getcwd() в модуле os возвращает строку. Поэтому, чтобы изменить путь, можно вручную изменить эту строку. Однако необходимые изменения зависят от операционной системы, поскольку в разных системах используются разные форматы путей. Лучшим вариантом является использование os.path.join():

import os
cwd = os.getcwd()
output_path = os.path.join(cwd, "testing_os")
print(output_path)

# Результат:
# /Users/sg/Documents/GitHub/datacamp/testing_os

Путь, который возвращает os.path.join(), имеет правильный формат для используемой операционной системы. В результате возвращается строка с новым путем. Мы можем проверить, не существует ли уже такая вложенная директория, с помощью функции os.path.exists(), которая возвращает булево значение:

print(os.path.exists(output_path))

# Результат:
# False

False в выводе показывает, что путь, представленный output_path, еще не существует. Модуль os предоставляет инструменты для его создания. Функция os.mkdir() создает новый каталог:

os.mkdir(output_path)
print(os.path.exists(output_path))

# Результат:
# True

Теперь новый подкаталог существует и в нем могут быть сохранены новые файлы:

output_file = os.path.join(output_path, "test.txt")
with open(output_file, "w") as file:
    file.write("Testing path modification with the 'os' module")

Переменная output_file содержит имя желаемого выходного файла с полным путем. Этот текстовый файл создается во вложенной папке /testing_os в текущей рабочей директории.

Мы также можем перечислить все элементы в папке с помощью os.listdir():

for item in os.listdir(output_path):
    print(item)

# Результат:
# test.txt

Функция os.listdir() возвращает список со всеми элементами в каталоге. Этот код итерирует этот список для отображения каждого файла или папки в отдельной строке. В этом примере каталог содержит один текстовый файл.

Примечание редакции: также рекомендуем статью «Как проверить существование файла с помощью Python».

Использование модуля pathlib

Более новый модуль pathlib также предоставляет инструменты для создания новых путей. Этот модуль использует оператор прямой косой черты / для объединения элементов в путь. Это тот же оператор, который используется для разделения числовых типов данных, а также символ, используемый в файловых путях в операционных системах POSIX.

Давайте создадим новый путь и проверим, не существует ли он уже:

from pathlib import Path
cwd = Path.cwd()
output_path = cwd / "testing_pathlib"
print(output_path)
print(Path.exists(output_path))

# Результат:
# /Users/sg/Documents/GitHub/datacamp/testing_pathlib
# False

Класс Path имеет собственный метод .mkdir() для создания новой директории:

Path.mkdir(output_path)
print(Path.exists(output_path))

# Результат:
#True

Поскольку output_path — это объект PosixPath или WindowsPath, мы можем использовать оператор прямой косой черты в любом месте, чтобы создать новый путь:

with open(output_path / "test.txt", "w") as file:
    file.write("Testing path modification with the 'pathlib' module")

Новый текстовый файл создается в папке /testing_pathlib.

Для перебора всех элементов в директории можно использовать метод Path .iterdir():

for item in Path.iterdir(output_path):
    print(item)

# Результат:
# /Users/sg/Documents/GitHub/datacamp/testing_pathlib/test.txt

Как и в других инструментах pathlib, возвращаемое значение не является строкой. Это объект PosixPath или WindowsPath. Мы можем использовать атрибут .name для отображения имени файла или папки без полного пути:

for item in Path.iterdir(output_path):
    print(item.name)

# Результат:
# test.txt

В то время как os.listdir() возвращает список, pathlib.Path.iterdir() возвращает объект-генератор:

print(Path.iterdir(cwd))

# Результат:
# <generator object Path.iterdir at 0x1036b2c20>

Такое поведение соответствует лучшим практикам современного Python, поскольку итераторы и генераторы более эффективны в определенных ситуациях.

Изменение текущей рабочей директории (CWD)

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

import os
from pathlib import Path
cwd = Path.cwd()
print(cwd)

os.chdir(cwd.parent)
cwd = Path.cwd()
print(cwd)

# Результат:
# /Users/sg/Documents/GitHub/datacamp
# /Users/sg/Documents/GitHub

Теперь рабочий каталог изменился. Мы также можем использовать cwd.parent.resolve(), чтобы убедиться в правильности обработки любых символических ссылок. Аргументом в os.chdir() также может быть строка, например, пути, возвращаемые функциями модуля os.

Будьте осторожны, изменяя рабочую директорию внутри программы, чтобы не допустить неожиданного поведения.

Лучшие практики и советы

Вот несколько лучших практик и советов при работе с путями в Python:

  • В новых проектах используйте pathlib. Это интуитивно понятный и объектно-ориентированный подход к работе с путями.
  • Следите за межплатформенной совместимостью. Используйте os.path.join() или оператор прямой косой черты в pathlib для создания путей, которые будут работать в различных операционных системах.
  • Проверяйте существование путей. Всегда проверяйте, не существует ли уже такой путь, прежде чем проводить с ним какие-либо манипуляции. В этом вам помогут os.psth.exists() и Path.Exists().
  • Не меняйте текущую директорию без необходимости. Чем меньше случаев смены рабочей директории, тем меньше вероятность неожиданного поведения программы и проще поддержка кода.
  • Реализуйте обработку ошибок. Используйте блоки try-except для управления ошибками в файловых операциях и предоставления осмысленных сообщений об ошибках.
  • Ставьте безопасность на первое место. При конструировании путей проверяйте пользовательский ввод, чтобы предотвратить атаки на директории.

Заключение

Навигация по файловой системе и манипулирование путями к файлам — частое требование во многих программах на Python. Модуль os предоставляет традиционные функции для решения этих задач, а модуль pathlib предлагает более современный, объектно-ориентированный подход. Использование pathlib не только упрощает многие операции, но и гарантирует, что ваш код останется кроссплатформенным и легко читаемым.

Независимо от того, поддерживаете ли вы существующую кодовую базу, использующую os, или начинаете новый проект, в котором можно использовать pathlib, знакомство с обоими модулями и их возможностями обеспечит вам гибкость и уверенность в управлении путями в любом проекте на Python.

Перевод статьи «How to Get the Current Directory in Python».