Поиск директории активного скрипта в Python: всесторонний обзор методов
Получение пути к текущему скрипту в Python
Как получить абсолютный путь к файлу исполняемого скрипта без учёта символических ссылок?
Наиболее надёжный способ - использовать комбинацию __file__ и os.path.realpath() (или pathlib.Path.resolve()). Этот метод работает в большинстве случаев, когда скрипт запускается напрямую или импортируется как модуль.
import os
script_path = os.path.realpath(__file__)
print(script_path)Python find path (поиск пути к файлу или директории в python (os.path, pathlib))
Пояснение: __file__ содержит путь к файлу, переданному интерпретатору (может быть относительным). Функция os.path.realpath() разрешает все символьные ссылки и возвращает канонический абсолютный путь. Аналог в pathlib: Path(__file__).resolve().
Возможные проблемы: __file__ может быть не определён, если интерпретатор запущен в интерактивном режиме или код выполняется через exec. В таких случаях путь не получить. Решение: использовать sys.argv[0] или inspect, но с оговорками.
Цель: получение точного местоположения скрипта для чтения сопутствующих файлов, логирования или самодиагностики.
Как получить путь к скрипту, если __file__ недоступен?
Используйте sys.argv[0]. Этот список содержит аргументы командной строки; первый элемент - имя запускаемого скрипта (может быть относительным).
import sys
import os
script_path = os.path.abspath(sys.argv[0])
print(script_path)Source file python (получение пути к текущему скрипту (source file) в python)
Пояснение: os.path.abspath() преобразует относительный путь в абсолютный, но не разрешает символьные ссылки. Если нужно разрешить, добавьте os.path.realpath().
Проблема: при запуске скрипта через -c или в интерактивном режиме sys.argv[0] может быть пустой строкой или содержать не путь, а строку '-c'. Этот способ не подходит для модуля, импортированного из другого скрипта.
Цель: запасной вариант, когда __file__ не задан.
Как получить путь к текущему фрейму (стеку вызовов) внутри функции?
Используйте модуль inspect для получения информации о вызывающем фрейме.
import inspect
import os
frame = inspect.currentframe()
if frame:
script_path = os.path.realpath(inspect.getfile(frame))
print(script_path)
del frame # чтобы избежать циклических ссылокPython program files path (путь к папке program files в windows из python)
Пояснение: inspect.currentframe() возвращает фрейм на момент вызова. inspect.getfile(frame) выдаёт имя файла, в котором определён код фрейма. Затем применяется realpath.
Проблема: в некоторых реализациях Python (например, PyPy) inspect.getfile может вернуть None или вызвать ошибку. Кроме того, после использования нужно удалить фрейм (del frame) для предотвращения утечки памяти.
Цель: получение пути к файлу, где объявлена текущая функция, даже если она импортирована из другого модуля.
Как получить путь к главному скрипту (main) внутри импортированного модуля?
Можно использовать sys.modules['__main__'] и его атрибут __file__.
import sys
import os
main_module = sys.modules.get('__main__')
if hasattr(main_module, '__file__'):
main_script_path = os.path.realpath(main_module.__file__)
print(main_script_path)
else:
print('Основной скрипт не является файлом (например, REPL)')
Пояснение: sys.modules['__main__'] - модуль, выполняемый как точка входа. Если он загружен из файла, у него есть __file__.
Проблема: если основной скрипт запущен через -c или -m, __file__ может отсутствовать или быть равен None. В таких случаях метод не сработает.
Цель: получение пути к «главному» скрипту из вспомогательного модуля (например, для чтения конфигурации рядом с точкой входа).
Как получить путь к директории скрипта?
Достаточно взять директорию от пути к скрипту:
import os
script_dir = os.path.dirname(os.path.realpath(__file__))
print(script_dir)
# С pathlib
from pathlib import Path
script_dir = Path(__file__).resolve().parent
print(script_dir)
Пояснение: os.path.dirname или атрибут parent у Path возвращают родительскую директорию.
Цель: создание путей к файлам, лежащим рядом со скриптом.
Расширенные примеры получения пути к скрипту
Пример 1. Разрешение символических ссылок с резервным вариантом
import os
import sys
# Пытаемся получить путь через __file__
try:
script_path = os.path.realpath(__file__)
except NameError:
# Если __file__ не определён (например, в REPL), используем sys.argv[0]
if sys.argv and sys.argv[0] and sys.argv[0] != '-c':
script_path = os.path.realpath(sys.argv[0])
else:
script_path = None
if script_path:
print(f'Путь к скрипту: {script_path}')
print(f'Директория: {os.path.dirname(script_path)}')
else:
print('Не удалось определить путь к скрипту')
Путь к скрипту: /home/user/project/script.py Директория: /home/user/project
Пример 2. Использование pathlib для работы с путями
from pathlib import Path
import sys
# Текущий скрипт
current = Path(__file__).resolve()
print(f'Полный путь: {current}')
print(f'Имя файла: {current.name}')
print(f'Стем (имя без расширения): {current.stem}')
print(f'Расширение: {current.suffix}')
# Директория и файл рядом
config = current.parent / 'config.ini'
print(f'Конфигурационный файл: {config}')
# Относительный путь от домашней директории
home = Path.home()
rel = current.relative_to(home)
print(f'Относительно home: {rel}')
Полный путь: /home/user/project/script.py Имя файла: script.py Стем (имя без расширения): script Расширение: .py Конфигурационный файл: /home/user/project/config.ini Относительно home: project/script.py
Пример 3. Получение пути в импортированном модуле к основному скрипту
# main.py
import utils
print('Главный скрипт:', __file__)
utils.show_main_path()
# utils.py
import sys
import os
def show_main_path():
main_mod = sys.modules.get('__main__')
if main_mod and hasattr(main_mod, '__file__'):
main_path = os.path.realpath(main_mod.__file__)
print(f'Из модуля utils: основной скрипт - {main_path}')
else:
print('Основной модуль не имеет файлового пути')
Главный скрипт: /home/user/project/main.py Из модуля utils: основной скрипт - /home/user/project/main.py
Пример 4. Работа с замороженными приложениями (PyInstaller, cx_Freeze)
import sys
import os
# В скомпилированном приложении __file__ может указывать на временный файл или не существовать
if getattr(sys, 'frozen', False):
# Приложение упаковано
application_path = os.path.realpath(sys.executable)
else:
application_path = os.path.realpath(__file__)
print(f'Путь к приложению: {application_path}')
print(f'Директория: {os.path.dirname(application_path)}')
Путь к приложению: /usr/local/bin/myapp.exe Директория: /usr/local/bin
Пример 5. Получение пути внутри функции с помощью inspect (с обработкой ошибок)
import inspect
import os
def get_current_script_path():
try:
frame = inspect.currentframe()
if frame is None:
return None
try:
filepath = inspect.getfile(frame)
finally:
del frame
return os.path.realpath(filepath)
except (TypeError, OSError):
return None
print(get_current_script_path())
/home/user/project/script.py