Подтвердить что ты не робот

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

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

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

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

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

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

4b9b3361

Ответ 1

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

Ответ 2

__file__

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

import os

os.path.realpath(__file__)

Ответ 3

Обновление 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

Ответ 4

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

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

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

print inspect.getfile(inspect.currentframe())

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

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

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

Ответ 5

import os
os.path.dirname(__file__) # relative directory path
os.path.abspath(__file__) # absolute file path
os.path.basename(__file__) # the file name only

Ответ 6

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

Если вы хотите узнать имя исполняемого файла (то есть корневой файл, переданный интерпретатору 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]

Ответ 7

import os
print os.path.basename(__file__)

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

Ответ 8

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

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

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

Ответ 9

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

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

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

Ответ 11

import os
os.path.dirname(os.path.abspath(__file__))

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

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

Ответ 12

Попробуй это,

import os
os.path.dirname(os.path.realpath(__file__))

Ответ 13

import sys

print sys.path[0]

это будет печатать путь текущего выполняющегося script

Ответ 14

Я думаю, что это просто __file__ Похоже, вы также можете проверить проверить модуль.

Ответ 15

Вы можете использовать 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'

Ответ 16

import sys
print sys.argv[0]

Ответ 17

Это должно работать:

import os,sys
filename=os.path.basename(os.path.realpath(sys.argv[0]))
dirname=os.path.dirname(os.path.realpath(sys.argv[0]))

Ответ 18

print(__file__)
print(__import__("pathlib").Path(__file__).parent)

Ответ 19

Чтобы получить каталог выполнения script

 print os.path.dirname( inspect.getfile(inspect.currentframe()))

Ответ 20

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

Ответ 21

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

Ответ 22

Чтобы сохранить согласованность миграции между платформами (macOS/Windows/Linux), попробуйте:

path = r'%s' % os.getcwd().replace('\\','/')

Ответ 23

Самый простой способ:

в script_1.py:

import subprocess
subprocess.call(['python3',<path_to_script_2.py>])

в script_2.py:

sys.argv[0]

PS: Я пробовал execfile, но поскольку он читает script_2.py как строку, sys.argv[0] возвращает <string>.

Ответ 24

Я всегда только использовал функцию os текущего рабочего каталога или CWD. Это часть стандартной библиотеки, и ее очень легко реализовать. Вот пример:

    import os
    base_directory = os.getcwd()

Ответ 25

Вот то, что я использую, чтобы я мог бросить свой код в любом месте без проблем. __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__))

Ответ 26

Поскольку Python 3 является довольно распространенным, я хотел включить ответ pathlib, так как считаю, что сейчас он, вероятно, является лучшим инструментом для доступа к информации о файлах и путях.

from pathlib import Path

current_file: Path = Path(__file__).resolve()

Если вы ищете каталог текущего файла, это так же просто, как добавить .parent в оператор Path():

current_path: Path = Path(__file__).parent.resolve()

Ответ 27

Большинство из этих ответов были написаны на 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

Ответ 28

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

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

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

Ответ 29

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)