Как мне получить путь и имя файла, который выполняется в данный момент?
Вопрос
У меня есть скрипты, вызывающие другие файлы скриптов, но мне нужно получить путь к файлу, который в данный момент выполняется в процессе.
Например, допустим, у меня есть три файла.Используя исполнительный файл:
script_1.py
звонкиscript_2.py
.- В свою очередь,
script_2.py
звонкиscript_3.py
.
Как я могу получить имя файла и путь к нему script_3.py
, из кода внутри script_3.py
, без необходимости передавать эту информацию в качестве аргументов из script_2.py
?
(Исполняющий os.getcwd()
возвращает путь к файлу исходного стартового скрипта, а не текущего файла.)
Решение
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
Другие советы
__file__
как говорили другие.Вы также можете захотеть использовать os.path.реальный путь чтобы исключить символические ссылки:
import os
os.path.realpath(__file__)
Обновление 2018-11-28:
Вот краткое изложение экспериментов с Python 2 и 3.С
main.py - работает foo.py
foo.py - работает lib/bar.py
lib/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
Выпьем за то, чтобы они были добавлены в система как функционирует!Спасибо @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
Я думаю, что это чище:
import inspect
print inspect.stack()[0][1]
и получает ту же информацию, что и:
print inspect.getfile(inspect.currentframe())
Где [0] - текущий кадр в стеке (верхняя часть стека), а [1] - имя файла, увеличьте, чтобы вернуться назад в стеке, т.е.
print inspect.stack()[1][1]
это было бы имя файла скрипта, который вызвал текущий фрейм.Кроме того, использование [-1] приведет вас к нижней части стека, к исходному вызывающему скрипту.
import os
os.path.dirname(__file__) # relative directory path
os.path.abspath(__file__) # absolute file path
os.path.basename(__file__) # the file name only
Все предложения, отмеченные как наилучшие, верны, если ваш скрипт состоит только из одного файла.
Если вы хотите узнать имя исполняемого файла (т. е.корневой файл, переданный интерпретатору 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]
import os
print os.path.basename(__file__)
это даст нам только имя файла.т. е.если abspath файла равен c:\abcd\abc.py, то будет выведена 2-я строка abc.py
Не совсем понятно, что вы подразумеваете под "путем к файлу, который в данный момент выполняется в процессе".sys.argv[0]
обычно содержит местоположение скрипта, который был вызван интерпретатором Python.Проверьте системная документация для получения более подробной информации.
Как указали @Tim и @Pat Notz, атрибут __file__ предоставляет доступ к
файл, из которого был загружен модуль , если он был загружен из файла
У меня есть скрипт, который должен работать в среде Windows.Этот сокращенный код - это то, с чем я закончил:
import os,sys
PROJECT_PATH = os.path.abspath(os.path.split(sys.argv[0])[0])
это довольно хитрое решение.Но для этого не требуется никаких внешних библиотек, и это самое важное в моем случае.
import os
os.path.dirname(os.path.abspath(__file__))
Нет необходимости в inspect или какой-либо другой библиотеке.
Это сработало у меня, когда мне пришлось импортировать скрипт (из другого каталога, чем выполняемый скрипт), который использовал файл конфигурации, находящийся в той же папке, что и импортированный скрипт.
Тот Самый __file__
атрибут работает как для файла, содержащего основной код выполнения, так и для импортированных модулей.
Видишь https://web.archive.org/web/20090918095828/http://pyref.infogami.com/__file__
import sys
print sys.path[0]
при этом будет выведен путь к текущему исполняемому скрипту
Я думаю, что это просто __file__
Похоже, вы также можете захотеть оформить заказ проверить модуль.
Вы можете использовать inspect.stack()
import inspect,os
inspect.stack()[0] => (<frame object at 0x00AC2AC0>, 'g:\\Python\\Test\\_GetCurrentProgram.py', 15, '<module>', ['print inspect.stack()[0]\n'], 0)
os.path.abspath (inspect.stack()[0][1]) => 'g:\\Python\\Test\\_GetCurrentProgram.py'
Попробуй это,
import os
os.path.dirname(os.path.realpath(__file__))
import sys
print sys.argv[0]
Это должно сработать:
import os,sys
filename=os.path.basename(os.path.realpath(sys.argv[0]))
dirname=os.path.dirname(os.path.realpath(sys.argv[0]))
Чтобы получить каталог исполняемого скрипта
print os.path.dirname( inspect.getfile(inspect.currentframe()))
Чтобы обеспечить согласованность миграции на разных платформах (macOS / Windows / Linux), попробуйте:
path = r'%s' % os.getcwd().replace('\\','/')
print(__file__)
print(__import__("pathlib").Path(__file__).parent)
Я использовал этот подход с __file__
os.path.abspath(__file__)
но есть небольшая хитрость, она возвращает файл .py
при первом запуске кода
при следующих запусках присваивается имя файла *.pyc
так что я остался с:
inspect.getfile(inspect.currentframe())
или
sys._getframe().f_code.co_filename
Я написал функцию, которая учитывает eclipse отладчик и наименьший.Он возвращает папку первого запущенного вами скрипта.Вы можете дополнительно указать __файл__ var, но главное заключается в том, что вам не нужно совместно использовать эту переменную во всех ваших иерархия вызовов.
Может быть, вы справитесь с другими конкретными случаями, которых я не видел, но для меня это нормально.
import inspect, os
def getRootDirectory(_file_=None):
"""
Get the directory of the root execution file
Can help: http://stackoverflow.com/questions/50499/how-do-i-get-the-path-and-name-of-the-file-that-is-currently-executing
For eclipse user with unittest or debugger, the function search for the correct folder in the stack
You can pass __file__ (with 4 underscores) if you want the caller directory
"""
# If we don't have the __file__ :
if _file_ is None:
# We get the last :
rootFile = inspect.stack()[-1][1]
folder = os.path.abspath(rootFile)
# If we use unittest :
if ("/pysrc" in folder) & ("org.python.pydev" in folder):
previous = None
# We search from left to right the case.py :
for el in inspect.stack():
currentFile = os.path.abspath(el[1])
if ("unittest/case.py" in currentFile) | ("org.python.pydev" in currentFile):
break
previous = currentFile
folder = previous
# We return the folder :
return os.path.dirname(folder)
else:
# We return the folder according to specified __file__ :
return os.path.dirname(os.path.realpath(_file_))
Самый простой способ - это:
в script_1.py:
import subprocess
subprocess.call(['python3',<path_to_script_2.py>])
в script_2.py:
sys.argv[0]
P.S.:Я пытался execfile
, но поскольку он читается script_2.py как строка, sys.argv[0]
возвращенный <string>
.
Я всегда просто использовал функцию операционной системы Текущего рабочего каталога, или CWD.Это часть стандартной библиотеки, и ее очень легко реализовать.Вот такой пример:
import os
base_directory = os.getcwd()
Большинство из этих ответов были написаны на Python версии 2.x или более ранней.В Python 3.x синтаксис функции print изменен на требование использования круглых скобок, т.е.печать().
Итак, этот более ранний ответ с высоким баллом от user13993 в Python 2.x:
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
Становится в Python 3.x:
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
если вам нужно только имя файла без ./
или .py
вы можете попробовать это
filename = testscript.py
file_name = __file__[2:-3]
file_name
будет напечатан testscript
вы можете сгенерировать все, что захотите, изменив индекс внутри []
import os
import wx
# return the full path of this file
print(os.getcwd())
icon = wx.Icon(os.getcwd() + '/img/image.png', wx.BITMAP_TYPE_PNG, 16, 16)
# put the icon on the frame
self.SetIcon(icon)