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

StackOverflow https://stackoverflow.com/questions/50499

  •  09-06-2019
  •  | 
  •  

Вопрос

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

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

  • 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)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top