Получение местоположения (пути) запущенного файла в Python: __file__.

Бизнес

Чтобы получить местоположение (путь) запущенного файла сценария в Python, используйте __file__. Это полезно для загрузки других файлов на основе местоположения запущенного файла.

До версии Python 3.8 __file__ возвращает путь, указанный при выполнении команды python (или команды python3 в некоторых средах). Если указан относительный путь, возвращается относительный путь; если указан абсолютный путь, возвращается абсолютный путь.

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

Объясняется следующее содержание.

  • os.getcwd(),__file__
  • Получить имя файла и имя каталога текущего исполняемого файла.
  • Получить абсолютный путь к выполняемому файлу.
  • Считывает другие файлы, основываясь на местоположении текущего исполняемого файла.
  • Переместить текущий каталог в каталог выполняемого файла.
  • Одна и та же обработка может быть выполнена независимо от текущего каталога во время выполнения.

Информацию о получении и изменении текущего каталога (рабочего каталога) см. в следующей статье.

Обратите внимание, что __file__ нельзя использовать в Jupyter Notebook (.ipynb).
Каталог, в котором находится .ipynb, будет выполняться как текущий каталог, независимо от каталога, в котором запущен Jupyter Notebook.
В коде можно использовать os.chdir() для изменения текущего каталога.

os.getcwd() и __file__.

В Windows для проверки текущего каталога вместо pwd можно использовать команду dir.

pwd
# /Users/mbp/Documents/my-project/python-snippets/notebook

Создайте файл сценария Python (file_path.py) со следующим содержимым на нижнем уровне (data\src).

import os

print('getcwd:      ', os.getcwd())
print('__file__:    ', __file__)

Запустите команду python (или команду python3 в некоторых средах), указав путь к файлу сценария.

python3 data/src/file_path.py
# getcwd:       /Users/mbp/Documents/my-project/python-snippets/notebook
# __file__:     data/src/file_path.py

Абсолютный путь к текущему каталогу можно получить с помощью os.getcwd(). Вы также можете использовать __file__ для получения пути, указанного командой python3.

До версии Python 3.8 __file__ будет содержать путь, указанный в команде python (или python3). В приведенном выше примере возвращается относительный путь, потому что он относительный, а абсолютный путь возвращается, если он абсолютный.

pwd
# /Users/mbp/Documents/my-project/python-snippets/notebook

python3 /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
# getcwd:       /Users/mbp/Documents/my-project/python-snippets/notebook
# __file__:     /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py

Python 3.9 и более поздние версии возвращают абсолютный путь к __file__, независимо от пути, указанного в команде python (или python3).

В следующем примере мы добавим код в тот же файл сценария (file_path.py) в Python 3.7 и запустим его относительно указанного выше каталога.

В Python 3.7 используется абсолютный путь. Результаты показаны в конце этого раздела.

Получить имя файла и имя каталога текущего исполняемого файла.

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

  • os.path.basename()
  • os.path.dirname()
print('basename:    ', os.path.basename(__file__))
print('dirname:     ', os.path.dirname(__file__))

Результат выполнения.

# basename:     file_path.py
# dirname:      data/src

Получить абсолютный путь к выполняемому файлу.

Если относительный путь получен с помощью __file__, он может быть преобразован в абсолютный с помощью os.path.abspath(). Каталоги также могут быть получены как абсолютные пути.

print('abspath:     ', os.path.abspath(__file__))
print('abs dirname: ', os.path.dirname(os.path.abspath(__file__)))

Результат выполнения.

# abspath:      /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
# abs dirname:  /Users/mbp/Documents/my-project/python-snippets/notebook/data/src

Если в os.path.abspath() указан абсолютный путь, он будет возвращен как есть. Поэтому, если __file__ является абсолютным путем, то следующие действия не приведут к ошибке.

  • os.path.abspath(__file__)

Считывает другие файлы, основываясь на местоположении текущего исполняемого файла.

Если вы хотите читать другие файлы на основе расположения (пути) выполняемого файла, объедините следующие два файла с помощью os.path.join().

  • Каталог выполняемого файла
  • Относительный путь к файлу, который будет считан из запущенного файла.

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

print('[set target path 1]')
target_path_1 = os.path.join(os.path.dirname(__file__), 'target_1.txt')

print('target_path_1: ', target_path_1)

print('read target file:')
with open(target_path_1) as f:
    print(f.read())

Результат выполнения.

# [set target path 1]
# target_path_1:  data/src/target_1.txt
# read target file:
# !! This is "target_1.txt" !!

Верхний уровень представлен «. \». Вы можете оставить его как есть, но можете использовать os.path.normpath() для нормализации пути и удаления лишних «. \» и другие символы.

print('[set target path 2]')
target_path_2 = os.path.join(os.path.dirname(__file__), '../dst/target_2.txt')

print('target_path_2: ', target_path_2)
print('normalize    : ', os.path.normpath(target_path_2))

print('read target file:')
with open(target_path_2) as f:
    print(f.read())

Результат выполнения.

# [set target path 2]
# target_path_2:  data/src/../dst/target_2.txt
# normalize    :  data/dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!

Переместить текущий каталог в каталог выполняемого файла.

Используйте os.chdir() для перемещения текущего каталога в каталог файла, выполняемого в сценарии.

Вы можете видеть, что он перемещается с помощью os.getcwd().

print('[change directory]')
os.chdir(os.path.dirname(os.path.abspath(__file__)))
print('getcwd:      ', os.getcwd())

Результат выполнения.

# [change directory]
# getcwd:       /Users/mbp/Documents/my-project/python-snippets/notebook/data/src

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

print('[set target path 1 (after chdir)]')
target_path_1 = 'target_1.txt'

print('target_path_1: ', target_path_1)

print('read target file:')
with open(target_path_1) as f:
    print(f.read())

print()
print('[set target path 2 (after chdir)]')
target_path_2 = '../dst/target_2.txt'

print('target_path_2: ', target_path_2)

print('read target file:')
with open(target_path_2) as f:
    print(f.read())

Результат выполнения.

# [set target path 1 (after chdir)]
# target_path_1:  target_1.txt
# read target file:
# !! This is "target_1.txt" !!
# 
# [set target path 2 (after chdir)]
# target_path_2:  ../dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!

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

Как мы показали, можно загружать файлы на основе расположения файла сценария, независимо от текущего каталога во время выполнения, используя один из следующих методов.

  • Соедините каталог запущенного файла и относительный путь к файлу, который будет считан из запущенного файла, с помощью os.path.join().
  • Переместить текущий каталог в каталог выполняемого файла.

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

Результаты предыдущих примеров обобщены ниже.

pwd
# /Users/mbp/Documents/my-project/python-snippets/notebook

python3 data/src/file_path.py
# getcwd:       /Users/mbp/Documents/my-project/python-snippets/notebook
# __file__:     data/src/file_path.py
# basename:     file_path.py
# dirname:      data/src
# abspath:      /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
# abs dirname:  /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
# 
# [set target path 1]
# target_path_1:  data/src/target_1.txt
# read target file:
# !! This is "target_1.txt" !!
# 
# [set target path 2]
# target_path_2:  data/src/../dst/target_2.txt
# normalize    :  data/dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!
# 
# [change directory]
# getcwd:       /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
# 
# [set target path 1 (after chdir)]
# target_path_1:  target_1.txt
# read target file:
# !! This is "target_1.txt" !!
# 
# [set target path 2 (after chdir)]
# target_path_2:  ../dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!

Результат указания абсолютного пути выглядит следующим образом.

pwd
# /Users/mbp/Documents/my-project/python-snippets/notebook

python3 /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
# getcwd:       /Users/mbp/Documents/my-project/python-snippets/notebook
# __file__:     /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
# basename:     file_path.py
# dirname:      /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
# abspath:      /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
# abs dirname:  /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
# 
# [set target path 1]
# target_path_1:  /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/target_1.txt
# read target file:
# !! This is "target_1.txt" !!
# 
# [set target path 2]
# target_path_2:  /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/../dst/target_2.txt
# normalize    :  /Users/mbp/Documents/my-project/python-snippets/notebook/data/dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!
# 
# [change directory]
# getcwd:       /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
# 
# [set target path 1 (after chdir)]
# target_path_1:  target_1.txt
# read target file:
# !! This is "target_1.txt" !!
# 
# [set target path 2 (after chdir)]
# target_path_2:  ../dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!

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

cd data/src

pwd
# /Users/mbp/Documents/my-project/python-snippets/notebook/data/src

python3 file_path.py
# getcwd:       /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
# __file__:     file_path.py
# basename:     file_path.py
# dirname:      
# abspath:      /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
# abs dirname:  /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
# 
# [set target path 1]
# target_path_1:  target_1.txt
# read target file:
# !! This is "target_1.txt" !!
# 
# [set target path 2]
# target_path_2:  ../dst/target_2.txt
# normalize    :  ../dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!
# 
# [change directory]
# getcwd:       /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
# 
# [set target path 1 (after chdir)]
# target_path_1:  target_1.txt
# read target file:
# !! This is "target_1.txt" !!
# 
# [set target path 2 (after chdir)]
# target_path_2:  ../dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!

Copied title and URL