Вопрос-Ответ

How do I get the path and name of the python file that is currently executing?

Как мне получить путь и имя файла python, который выполняется в данный момент?

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

Допустим, у меня есть три файла. Используя execfile:


  • script_1.py вызовы script_2.py.

  • В свою очередь, script_2.py вызывает script_3.py.

Как я могу получить имя файла и путь к script_3.py, из кода внутри script_3.py, без необходимости передавать эту информацию в качестве аргументов из script_2.py?

(Выполнение os.getcwd() возвращает путь к файлу исходного стартового скрипта, а не текущего файла.)

Переведено автоматически
Ответ 1
__file__

как говорили другие. Вы также можете использовать os.path.realpath для устранения символических ссылок:

import os

os.path.realpath(__file__)
Ответ 2

p1.py:

execfile("p2.py")

p2.py:

import inspect, os
print (inspect.getfile(inspect.currentframe())) # script filename (usually with path)
print (os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))) # script directory
Ответ 3

Обновление 2018-11-28:

Вот краткое изложение экспериментов с Python 2 и 3. С

main.py - выполняется foo.py
foo.py - выполняется lib/bar.py
библиотека /bar.py - выводит выражения пути к файлу

| Python | Run statement       | Filepath expression                    |
|--------+---------------------+----------------------------------------|
| 2 | execfile | os.path.abspath(inspect.stack()[0][1]) |
| 2 | from lib import bar | __file__ |
| 3 | exec | (wasn't able to obtain it) |
| 3 | import lib.bar | __file__ |

Для Python 2, возможно, было бы понятнее переключиться на пакеты, поэтому можно использовать from lib import bar - просто добавьте пустые __init__.py файлы в две папки.

Для Python 3 execfile не существует - ближайшая альтернатива - exec(open(<filename>).read()), хотя это влияет на фреймы стека. Проще всего просто использовать import foo и import lib.bar - никаких __init__.py файлов не требуется.

Смотрите также Разница между import и execfile


Оригинальный ответ:

Вот эксперимент, основанный на ответах в этой теме - с Python 2.7.10 в Windows.

Основанные на стеке - единственные, которые, кажется, дают надежные результаты. Последние два имеют самый короткий синтаксис, т.е. -

print os.path.abspath(inspect.stack()[0][1])                   # C:\filepaths\lib\bar.py
print os.path.dirname(os.path.abspath(inspect.stack()[0][1])) # C:\filepaths\lib

Они добавляются в sys как функции! Спасибо @Usagi и @pablog

На основе следующих трех файлов и выполняется main.py из его папки с помощью python main.py (также пробовал execfiles с абсолютными путями и вызовом из отдельной папки).

C:\filepaths\main.py: execfile('foo.py')
C:\filepaths\foo.py: execfile('lib/bar.py')
C:\filepaths\lib\bar.py:

import sys
import os
import inspect

print "Python " + sys.version
print

print __file__ # main.py
print sys.argv[0] # main.py
print inspect.stack()[0][1] # lib/bar.py
print sys.path[0] # C:\filepaths
print

print os.path.realpath(__file__) # C:\filepaths\main.py
print os.path.abspath(__file__) # C:\filepaths\main.py
print os.path.basename(__file__) # main.py
print os.path.basename(os.path.realpath(sys.argv[0])) # main.py
print

print sys.path[0] # C:\filepaths
print os.path.abspath(os.path.split(sys.argv[0])[0]) # C:\filepaths
print os.path.dirname(os.path.abspath(__file__)) # C:\filepaths
print os.path.dirname(os.path.realpath(sys.argv[0])) # C:\filepaths
print os.path.dirname(__file__) # (empty string)
print

print inspect.getfile(inspect.currentframe()) # lib/bar.py

print os.path.abspath(inspect.getfile(inspect.currentframe())) # C:\filepaths\lib\bar.py
print os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) # C:\filepaths\lib
print

print os.path.abspath(inspect.stack()[0][1]) # C:\filepaths\lib\bar.py
print os.path.dirname(os.path.abspath(inspect.stack()[0][1])) # C:\filepaths\lib
print
Ответ 4

Я думаю, что это чище:

import inspect
print inspect.stack()[0][1]

и получает ту же информацию, что и:

print inspect.getfile(inspect.currentframe())

Где [0] - текущий фрейм в стеке (вершина стека), а [1] - имя файла, увеличьте, чтобы вернуться назад в стеке, т.е.

print inspect.stack()[1][1]

это будет имя файла скрипта, который вызвал текущий фрейм. Кроме того, использование [-1] приведет вас к нижней части стека, исходному вызывающему скрипту.

2023-10-24 06:42 python file