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

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

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

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

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

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

23 ответов


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.путь.реального пути для устранения символических ссылок:

import os

os.path.realpath(__file__)

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

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

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

вот к этим добавляется sys как функции! Кредит @Usagi и @pablog

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

C:\testpath\script1.py: execfile('script2.py')
C:\testpath\script2.py: execfile('lib/script3.py')
C:\testpath\lib\script3.py:

import sys
import os
import inspect

print "Python " + sys.version
print

print __file__                                        # script1.py
print sys.argv[0]                                     # script1.py
print inspect.stack()[0][1]                           # lib/script3.py
print sys.path[0]                                     # C:\testpath
print

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

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

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

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

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

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

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

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

print inspect.getfile(inspect.currentframe())

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

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

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


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

если вы хотите узнать имя исполняемого файла (т. е. корневого файла, переданного интерпретатору 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
os.path.dirname(__file__) # relative directory path
os.path.abspath(__file__) # absolute file path
os.path.basename(__file__) # the file name only

import os
print os.path.basename(__file__)

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


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

как указали @Tim и @Pat Notz, атрибут _ _ file_ _ предоставляет доступ к

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


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

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

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


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

см https://web.archive.org/web/20090918095828/http://pyref.infogami.com/__file__


import os
os.path.dirname(os.path.abspath(__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 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('\','/')


я использовал подход с _ _ file__
os.path.abspath(__file__)
но есть маленькая хитрость, она возвращает .файл py при первом запуске кода, следующие прогоны дают имя *.файл pyc
поэтому я остался с:
inspect.getfile(inspect.currentframe())
или
sys._getframe().f_code.co_filename


Я написал функцию, которая учитывает eclipse отладчик и unittest. Он возвращает папку первого сценария, который вы запускаете. Вы можете дополнительно указать __файл__ 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>.


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)

если вы хотите только имя файла без ./ или .py вы можете попробовать этот

filename = testscript.py
file_name = __file__[2:-3]

file_name будет печатать testscript вы можете генерировать все, что хотите, изменив индекс внутри []