Поиск директории активного скрипта в 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

Получение пути к текущему скрипту (source file) в Python - comments

En
Source file python (python)