У меня есть сценарии, вызывающие другие файлы сценариев, но мне нужно получить путь к файлу, который в настоящее время выполняется в процессе.
Например, у меня есть три файла. Используя execfile:
script_1.py вызывает script_2.py.script_2.py вызывает script_3.py.Как я могу получить имя файла и путь к script_3.py, из кода в script_3.py, не передавая эту информацию в качестве аргументов от script_2.py?
(Выполнение os.getcwd() возвращает исходный путь к файлу начального сценария, а не путь к текущему файлу.)
os.path.realpath (файл)
связанные: Как правильно определить текущий каталог скрипта?






Не совсем понятно, что вы подразумеваете под «путем к файлу, который в данный момент выполняется в процессе».
sys.argv[0] обычно содержит расположение сценария, запущенного интерпретатором Python.
Проверьте sys документация для более подробной информации.
Как отметили @Tim и @Pat Notz, атрибут __file__ обеспечивает доступ к
the file from which the module was loaded, if it was loaded from a file
«print os.path.abspath (файл)» и «print inspect.getfile (inspect.currentframe ())» не работают, когда мы передаем программу python в win32 exe. Работает только sys.argv [0]! :) а ты только имя узнаешь!
Я думаю, это просто __file__. Похоже, вы также можете проверить проверить модуль.
Аааа ... execfile - это сложно. См. Другой мой пост об использовании модуля проверки.
Атрибут __file__ работает как для файла, содержащего основной код выполнения, так и для импортированных модулей.
См. https://web.archive.org/web/20090918095828/http://pyref.infogami.com/__file__
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
@David, когда я делаю inspect.getfile(inspect.currentframe()), он дает мне полный путь к обрабатываемому файлу. Поэтому я не уверен, что вы имеете в виду или при каких условиях это не дало бы «имя и путь».
Оно делает? Не для меня и еще нескольких, судя по всему. Вторая строка, которая была добавлена к ответу, дает полный путь, хотя
ВНИМАНИЕ: этот вызов не дает одинакового результата в разных средах. Вы можете принять ответ Усаги ниже: stackoverflow.com/a/6628348/851398
@faraday: Не могли бы вы привести пример? Я ответил аналогичный вопрос с использованием inspect.getabsfile(), и он работал во всех случаях, которые я пробовал.
Действительно ли @Usagi отвечает лучше?
нет, user13993 прибил это намного лучше
user13993 действительно пригвоздил. Должен быть os.path.realpath(__file__)
Метод @Dror user13933 дает мне имя вызывающего, а не вызываемого. Это правильно для заданного вопроса.
@osirisgothra: вы понимаете, что __file__ не работает с execfile(), который упоминается в вопросе явно.
Хотя файл обычно достаточно хорош, он не будет работать, если ваша программа работает где-то далеко от файл.
inspect.getfile() возвращает атрибут __file__, если передан объект модуля. inspect.currentframe() возвращает модуль. Ergo, это дорогой способ сказать __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'
__file__
как говорили другие. Вы также можете использовать os.path.realpath для удаления символических ссылок:
import os
os.path.realpath(__file__)
С этим подходом нужно быть осторожным, потому что иногда __file__ возвращает «script_name.py», а иногда «script_name.pyc». Так что выход нестабилен.
Но поскольку мы используем только путь к этому файлу, это не имеет значения.
это странно: при запуске из командной строки "__file__" в кавычках (как строка) дает каталог, из которого запускается cmd, но __file__ (без кавычек дает путь к исходному файлу ... почему это
@muon не выполняется проверка того, существует ли переданная строка имени файла, и поскольку пути к файлам относятся к cwd, это то, что функция os.path.realpath предполагает, что часть пути dir является. os.path.dirname(os.path.realpath(__file__)) возвращает каталог с файлом. os.path.dirname(os.path.realpath("__file__")) возвращает cwd. os.path.dirname(os.path.realpath("here_be_dragons")) также возвращает cwd.
import sys
print sys.path[0]
это напечатает путь к исполняемому в данный момент скрипту
sys.path [0] очень полезен, но дает путь к сценарию 1, а не к сценарию 3, как было запрошено.
По крайней мере, на OS X с 2.7 я не считаю, что это что-то надежное. Он работает, если запускать один и тот же файл напрямую. Не работает репл, особенно от импортного яйца
Все предложения, отмеченные как лучшие, верны, если ваш сценарий состоит только из одного файла.
Если вы хотите узнать имя исполняемого файла (то есть корневой файл, переданный интерпретатору 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]Он работает хорошо, но не для модульного теста на eclipse, у меня есть /home/user/Softwares/eclipse/plugins/org.python.pydev_4.5.5. 201603221110 / pysrc
На самом деле это дорогостоящий способ написания sys.modules['__main__'].__file__.
import sys
print sys.argv[0]
К сожалению, это работает только в том случае, если сценарий был вызван с указанием полного пути, потому что он возвращает только «первый аргумент» в командной строке, который является вызовом сценария.
Я использовал подход с __file__os.path.abspath(__file__)
но есть небольшая хитрость, он возвращает файл .py
при первом запуске кода,
следующие прогоны дают имя * .pyc файла
поэтому я остался с: inspect.getfile(inspect.currentframe())
или sys._getframe().f_code.co_filename
Думаю, это чище:
import inspect
print inspect.stack()[0][1]
и получает ту же информацию, что и:
print inspect.getfile(inspect.currentframe())
Где [0] - текущий фрейм в стеке (верх стека), а [1] - это имя файла, увеличивайте, чтобы вернуться в стек, т. Е.
print inspect.stack()[1][1]
будет именем файла сценария, который вызвал текущий фрейм. Кроме того, использование [-1] приведет вас к нижней части стека, к исходному сценарию вызова.
Не рекомендую полагаться на позицию внутри кортежа. Совершенно непонятно, какие данные вы пытаетесь получить при чтении кода.
inspect.getfile() возвращает атрибут __file__, если передан объект модуля. inspect.currentframe() возвращает модуль. Ergo, это дорогой способ сказать __file__.
inspect.stack() - довольно дорогая функция, больше, чем просто inspect.currentframe(), и она также вызывает inspect.getfile() для объекта модуля.
У меня есть сценарий, который должен работать в среде Windows. Этот фрагмент кода - это то, с чем я закончил:
import os,sys
PROJECT_PATH = os.path.abspath(os.path.split(sys.argv[0])[0])
это довольно хакерское решение. Но для этого не нужны внешние библиотеки, и это самое главное в моем случае.
Для этого мне пришлось «импортировать os, sys», но пока это лучший ответ, который фактически возвращает только путь без имени файла в конце строки.
если вам нужно только имя файла без ./ или .py, вы можете попробовать это
filename = testscript.py
file_name = __file__[2:-3]
file_name распечатает тестовый скрипт
вы можете сгенерировать все, что захотите, изменив индекс внутри []
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)
os.getcwd () возвращает текущий РАБОЧИЙ каталог ПРОЦЕССА, а не каталог текущего исполняемого файла. Может показаться, что это возвращает правильные результаты, но во многих случаях результатом не будет родительский каталог текущего файла. Намного лучше использовать os.path.dirname (файл), как было предложено выше.
import os
print os.path.basename(__file__)
это даст нам только имя файла. т.е. если abspath файла - c: \ abcd \ abc.py, то вторая строка напечатает abc.py
import os
os.path.dirname(os.path.abspath(__file__))
Нет необходимости в проверке или какой-либо другой библиотеке.
Это сработало для меня, когда мне пришлось импортировать скрипт (из другого каталога, чем исполняемый скрипт), который использовал файл конфигурации, находящийся в той же папке, что и импортированный скрипт.
Это не даст желаемого ответа, если текущий рабочий каталог (os.getcwd) отличается от каталога, в котором находится файл.
Как так? В этом случае у меня работает нормально. Я получаю каталог, в котором находится файл.
@IronPillow, возможно, этот ответ поможет вам с тем, что вам нужно. stackoverflow.com/a/41546830/3123191
import os
os.path.dirname(__file__) # relative directory path
os.path.abspath(__file__) # absolute file path
os.path.basename(__file__) # the file name only
Я только что попробовал комментарий @Pat Notz. Я думаю, вы могли бы просто получить имя файла через __file__.
В Python3 os.path.dirname предоставит вам относительный путь, откуда вы запускаете скрипт. например в python ../../test.pyos.path.dirname будет ../../, а не абсолютным путем к сценарию. Я искал abspath, но удалял название скрипта. Очевидно, первым элементом sys.path является ответ sys.path[0].
Это должно работать:
import os,sys
filename=os.path.basename(os.path.realpath(sys.argv[0]))
dirname=os.path.dirname(os.path.realpath(sys.argv[0]))
Обновление 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
Вот они, добавленные в sys как функции! Кредит для @Usagi и @pablog
На основе следующих трех файлов и запуска main.py из его папки с python main.py (также пробовали файлы exec с абсолютными путями и вызовы из отдельной папки).
C: \ пути к файлам \ main.py: execfile('foo.py')
C: \ пути к файлам \ 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
Я написал функцию, которая учитывает затмения отладчик и модульный тест. Он возвращает папку с первым запускаемым вами скриптом. Вы можете дополнительно указать переменную __файл__, но главное, что вам не нужно использовать эту переменную для всех ваших иерархия вызовов.
Возможно, вы справитесь с другими частными случаями, которые я не видел, но для меня это нормально.
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_))
Получить каталог исполняемого скрипта
print os.path.dirname( inspect.getfile(inspect.currentframe()))
Чтобы обеспечить согласованность миграции между платформами (macOS / Windows / Linux), попробуйте:
path = r'%s' % os.getcwd().replace('\','/')
Это не правильно. Это даст вам текущий путь, но не путь к текущему файлу.
Самый простой способ:
в 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>.
Большинство этих ответов были написаны на 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
Я всегда просто использовал функцию ОС текущего рабочего каталога или CWD. Это часть стандартной библиотеки, и ее очень легко реализовать. Вот пример:
import os
base_directory = os.getcwd()
Не могли бы вы изменить свой ответ так, чтобы он относился к заданному вопросу? Этот ответ не относится к вопросу «Как мне получить путь и имя файла, который выполняется в данный момент?»
Это дает путь, по которому вы запустили команду python. Таким образом, кажется, что это работает, когда вы запускаете команду python script.py в той же папке, в которой вы уже находитесь, хотя на самом деле это то же самое, что запускать pwd в Linux.
Попробуй это,
import os
os.path.dirname(os.path.realpath(__file__))
print(__file__)
print(__import__("pathlib").Path(__file__).parent)
Ответы только на код не приветствуются. Пожалуйста, объясните, как это решает проблему или чем это отличается от существующих ответов. Из обзора
Вот что я использую, чтобы без проблем бросать свой код куда угодно. __name__ определяется всегда, но __file__ определяется только тогда, когда код запускается как файл (например, не в IDLE / iPython).
if '__file__' in globals():
self_name = globals()['__file__']
elif '__file__' in locals():
self_name = locals()['__file__']
else:
self_name = __name__
В качестве альтернативы это можно записать как:
self_name = globals().get('__file__', locals().get('__file__', __name__))
Поскольку Python 3 довольно распространен, я хотел включить ответ pathlib, так как считаю, что теперь это, вероятно, лучший инструмент для доступа к информации о файлах и путях.
from pathlib import Path
current_file: Path = Path(__file__).resolve()
Если вы ищете каталог текущего файла, это так же просто, как добавить .parent к оператору Path():
current_path: Path = Path(__file__).parent.resolve()
Связанный: Атрибут Python
__file__абсолютный или относительный?