Как я могу получить путь и имя файла, который выполняется в настоящее время? - PullRequest
441 голосов
/ 08 сентября 2008

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

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

  • script_1.py звонки script_2.py.
  • В свою очередь, script_2.py звонит script_3.py.

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

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

Ответы [ 27 ]

532 голосов
/ 23 декабря 2009
__file__

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

import os

os.path.realpath(__file__)
237 голосов
/ 09 сентября 2008

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
78 голосов
/ 07 августа 2015

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

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

main.py - запускает foo.py
foo.py - запускает lib / bar.py
lib / bar.py - печатает выражения filepath

| 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: \ Путь к файлам \ 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
68 голосов
/ 08 июля 2011

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

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

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

print inspect.getfile(inspect.currentframe())

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

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

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

40 голосов
/ 06 февраля 2015
import os
os.path.dirname(__file__) # relative directory path
os.path.abspath(__file__) # absolute file path
os.path.basename(__file__) # the file name only
36 голосов
/ 27 февраля 2010

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

Если вы хотите узнать имя исполняемого файла (то есть корневого файла, переданного интерпретатору python для текущей программы) из файла, который может быть импортирован как модуль, вам нужно сделать это (предположим, это в файле с именем foo.py ):

import inspect

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

Потому что последнее ([-1]) в стеке - это первое, что вошло в него (стеки - это структуры данных LIFO / FILO).

Затем в файле bar.py , если вы import foo напечатаете bar.py , а не foo.py , который будет стоимость всех этих:

  • __file__
  • inspect.getfile(inspect.currentframe())
  • inspect.stack()[0][1]
13 голосов
/ 11 августа 2013
import os
print os.path.basename(__file__)

это даст нам только имя файла. то есть, если abspath файла - c: \ abcd \ abc.py, то во 2-й строке будет напечатано abc.py

12 голосов
/ 08 сентября 2008

Не совсем понятно, что вы подразумеваете под "путём файла, который в данный момент выполняется в процессе". sys.argv[0] обычно содержит местоположение скрипта, который был вызван интерпретатором Python. Обратитесь к документации sys для получения более подробной информации.

Как отметили @Tim и @Pat Notz, атрибут __file__ обеспечивает доступ к

файл из которого был модуль загружен, если он был загружен из файла

10 голосов
/ 08 августа 2012

У меня есть скрипт, который должен работать в среде Windows. С этим фрагментом кода я закончил:

import os,sys
PROJECT_PATH = os.path.abspath(os.path.split(sys.argv[0])[0])

это довольно хакерское решение. Но это не требует никаких внешних библиотек, и это самое главное в моем случае.

8 голосов
/ 24 июня 2014
import os
os.path.dirname(os.path.abspath(__file__))

Нет необходимости для проверки или любой другой библиотеки.

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

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