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

Понимание структуры проекта и текущей директории — базовый навык для любого разработчика на Python. Текущая рабочая директория влияет на то, где ищутся файлы, как работают относительные импорты и куда будут записываться временные файлы. В этой статье собраны основные способы получить и изменить текущую директорию, рекомендации по организации проекта и практические советы безопасности и совместимости.
Краткое определение
Текущая рабочая директория — это каталог, относительно которого интерпретатор Python разрешает относительные пути по умолчанию. Одной строкой: cwd (current working directory) — это «текущая папка», от которой идут относительные пути.
Основные способы получить текущую директорию
В стандартной библиотеке есть всё, что нужно: модуль os и вспомогательный модуль shutil. Ниже — рабочие примеры.
Простой и распространённый метод — os.getcwd():
import os
CURR_DIR = os.getcwd()
print(CURR_DIR)Если код выполняется в файле и требуется узнать папку, где лежит сам файл, используйте file вместе с os.path:
import os
CURR_DIR = os.path.dirname(os.path.realpath(__file__))
print(CURR_DIR)Чтобы подняться на уровень выше (например, получить корень проекта), часто применяют двойной dirname с abspath:
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
print(BASE_DIR)Важно: file доступен, когда скрипт запускается как файл. В интерактивной оболочке (REPL) или некоторых окружениях (например, при запуске через certain runners) file может быть отсутствующим.
Как сменить текущую директорию
Чтобы программно изменить cwd, используйте os.chdir(path). Пример для Windows-пути (замените путь на свой):
import os
os.chdir('C:/Users/Omisola Idowu/Desktop/my_project')
print(os.getcwd())После выполнения os.chdir все относительные операции будут выполняться относительно новой директории.
Важно: chdir влияет на глобальное состояние процесса. В многопоточном приложении изменение cwd в одном потоке повлияет на другие.
Частые операции с директориями и файлами — «шпаргалка»
- os.listdir(path=’.’) — перечислить содержимое каталога (файлы и папки). Если path опущен, используется cwd.
- os.mkdir(‘new_dir’) — создать директорию в cwd или по абсолютному пути.
- os.makedirs(‘a/b/c’, exist_ok=True) — создать вложенные папки рекурсивно.
- os.rename(‘old’, ‘new’) — переименовать файл или папку.
- os.rmdir(‘folder_name’) — удалить пустую папку.
- os.remove(‘file_name’) — удалить файл.
- shutil.rmtree(‘folder_name’) — удалить непустую папку (требует import shutil).
Пример использования списка команд:
import os
import shutil
# список
print(os.listdir('.'))
# создать
os.makedirs('data/logs', exist_ok=True)
# удалить непустую
shutil.rmtree('data/old_logs')Совместимость между ОС
- На Windows допускаются оба варианта слешей, но рекомендуется использовать прямой слэш ‘/‘ или os.path.join для переносимости.
- Для сложных путей используйте pathlib (рекомендуется в современных проектах). pathlib автоматически работает с платформенными особенностями.
Пример с pathlib:
from pathlib import Path
cwd = Path.cwd()
print(cwd)
script_dir = Path(__file__).resolve().parent
print(script_dir)Когда метод может подвести
- file отсутствует в интерактивной сессии или при некоторых упаковках (frozen executables). В таких случаях используйте os.getcwd() или окружение, которое задаёт путь явно.
- os.chdir в многопоточном приложении не является потокобезопасным.
- При работе в контейнерах/CI cwd может отличаться от ожиданий — лучше явно задавать пути через переменные окружения или конфигурацию.
Альтернативные подходы и рекомендации
- Используйте pathlib для чистоты и читаемости кода.
- Для поиска корня проекта применяйте правила: искать по наличию файла pyproject.toml, setup.py, .git и т. п. Это надёжнее, чем жёстко вычислять dirname(file).
- Для тестов и временных файлов используйте временные директории (tempfile.TemporaryDirectory) вместо изменения cwd.
Мини-методология «Найти корень проекта» (быстрый чеклист):
- Начните с Path(file).resolve().parent.
- Поднимайтесь по родителям (parent) в цикле до тех пор, пока не найдёте один из маркеров: ‘.git’, ‘pyproject.toml’, ‘setup.py’, ‘requirements.txt’.
- Если маркер не найден — используйте рабочую директорию или бросьте понятное исключение.
Пример алгоритма на pathlib:
from pathlib import Path
markers = {'pyproject.toml', 'setup.py', '.git'}
current = Path(__file__).resolve().parent
for _ in range(10): # ограничение глубины
if any((current / m).exists() for m in markers):
project_root = current
break
if current.parent == current:
project_root = None
break
current = current.parent
print(project_root)Безопасность пути и уязвимости
- Никогда не подставляйте необработанные пользовательские данные в os.chdir, open или команды shell. Это риск path traversal или инъекции.
- Для валидации входящих путей используйте Path.resolve() и проверяйте, что результирующий путь находится внутри разрешённой корневой директории.
Пример безопасной проверки:
from pathlib import Path
base = Path('/srv/app/data').resolve()
candidate = (base / user_supplied_path).resolve()
if base in candidate.parents or base == candidate:
# путь безопасен
pass
else:
raise ValueError('Неверный путь')Роль-ориентированные чеклисты
Для начинающего разработчика:
- Понимайте разницу между os.getcwd() и Path.cwd().
- Не меняйте cwd глобально без необходимости.
- Используйте абсолютные пути при записи важных файлов.
Для бээнд-разработчика:
- В конфигурации сервиса явно задавайте рабочую директорию или используйте абсолютные пути.
- Защитите операции с файлами от path traversal.
Для DevOps/CI:
- В pipeline всегда явно задавайте директорию запуска.
- В контейнерах задавайте рабочую директорию через WORKDIR (Docker) или соответствующую опцию.
Cheatsheet: часто используемые вызовы
- Получить cwd: os.getcwd() или Path.cwd()
- Получить папку скрипта: os.path.dirname(os.path.realpath(file)) или Path(file).resolve().parent
- Поменять cwd: os.chdir(path)
- Создать вложенные каталоги: os.makedirs(path, exist_ok=True) или Path(path).mkdir(parents=True, exist_ok=True)
- Удалить непустую папку: shutil.rmtree(path)
Примеры реальных сценариев и когда это важно
- Тесты: тестовый фреймворк может запускать тесты из корня репозитория — используйте фикстуры, чтобы явно задавать пути.
- Веб-приложение: загрузка статических файлов должна использовать абсолютные пути, заданные в конфигурации, а не cwd.
- CLI-инструмент: позволяет опционально принимать –cwd или –project-root для надёжности.
Совместимость и миграция
- Если проект использует устаревшие относительные пути, постепенно мигрируйте на pathlib и конфигурируемые корни через переменные окружения.
- Для Windows-пользователей совет: избегайте жёстко прописанных путей с пробелами; используйте r’…’ или нормализацию через Path.
Факто-бокс — ключевые команды
- os.getcwd() — получить текущую рабочую директорию
- os.chdir(path) — сменить рабочую директорию
- Path.cwd(), Path(file).resolve().parent — pathlib-аналоги
- shutil.rmtree — удалить непустую папку
Критерии приёмки
- Сценарий: скрипт должен корректно определять корень проекта на локальной машине и в CI.
- Критерий 1: Корень определяется при наличии файла pyproject.toml или .git.
- Критерий 2: В интерактивной сессии функция возвращает cwd, а не вызывает исключение из-за отсутствия file.
- Критерий 3: Все операции с путями валидируются на предмет выхода за пределы разрешённого каталога.
Короткий глоссарий
- cwd — текущая рабочая директория (current working directory).
- file — путь к текущему исполняемому файлу Python, если он определён.
- pathlib — модуль для работы с путями в объектно-ориентированном стиле.
Краткое резюме
Понимание и контроль текущей директории в Python улучшает надёжность и переносимость приложений. Используйте os и pathlib, соблюдайте правила безопасности при работе с пользовательскими путями, а для корня проекта предпочитайте проверку по маркерам репозитория. В большинстве случаев pathlib делает код чище и менее подверженным ошибкам.
Примечание: при автоматизации и многопоточности избегайте глобальных смен cwd; вместо этого используйте явные абсолютные пути или контекстные менеджеры, возвращающие временные каталоги.