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

python scripting file

497173 просмотра

29 ответа

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

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

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

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

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

Автор: Ray Vega Источник Размещён: 23.08.2019 10:21

Ответы (29)


240 плюса

Решение

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
Автор: Pat Notz Размещён: 08.09.2008 11:02

540 плюса

__file__

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

import os

os.path.realpath(__file__)
Автор: user13993 Размещён: 23.12.2009 08:33

80 плюса

Обновление 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: \ 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
Автор: Brian Burns Размещён: 06.08.2015 10:50

69 плюса

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

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

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

print inspect.getfile(inspect.currentframe())

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

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

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

Автор: Usagi Размещён: 08.07.2011 05:50

40 плюса

import os
os.path.dirname(__file__) # relative directory path
os.path.abspath(__file__) # absolute file path
os.path.basename(__file__) # the file name only
Автор: Neal Xiong Размещён: 06.02.2015 01:05

37 плюса

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

Если вы хотите узнать имя исполняемого файла (т. Е. Корневой файл, переданный интерпретатору 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]
Автор: user282406 Размещён: 26.02.2010 10:25

13 плюса

import os
print os.path.basename(__file__)

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

Автор: vishal ekhe Размещён: 11.08.2013 03:05

12 плюса

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

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

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

Автор: Blair Conrad Размещён: 08.09.2008 07:42

10 плюса

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

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

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

Автор: garmoncheg Размещён: 08.08.2012 09:42

8 плюса

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

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

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

Автор: Kwuite Размещён: 24.06.2014 03:04

8 плюса

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

См. Https://web.archive.org/web/20090918095828/http://pyref.infogami.com/__file__

Автор: Readonly Размещён: 08.09.2008 07:56

7 плюса

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

import os
os.path.dirname(os.path.realpath(__file__))
Автор: Soumyajit Размещён: 22.02.2019 05:31

6 плюса

import sys

print sys.path[0]

это напечатало бы путь выполняемого в данный момент скрипта

Автор: appusajeev Размещён: 02.01.2010 06:34

5 плюса

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

Автор: Pat Notz Размещён: 08.09.2008 07:44

4 плюса

Ты можешь использовать 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'
Автор: PabloG Размещён: 09.09.2008 12:00

3 плюса

import sys
print sys.argv[0]
Автор: WBAR Размещён: 19.04.2010 07:47

2 плюса

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

import os,sys
filename=os.path.basename(os.path.realpath(sys.argv[0]))
dirname=os.path.dirname(os.path.realpath(sys.argv[0]))
Автор: Jahid Размещён: 14.06.2015 04:37

2 плюса

print(__file__)
print(__import__("pathlib").Path(__file__).parent)
Автор: BaiJiFeiLong Размещён: 05.05.2019 01:19

1 плюс

Получить каталог исполняемого скрипта

 print os.path.dirname( inspect.getfile(inspect.currentframe()))
Автор: pbaranski Размещён: 10.05.2017 10:51

0 плюса

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

Автор: mik80 Размещён: 01.03.2011 09:23

0 плюса

Я написал функцию, которая принимает во внимание отладчик затмения и unittest . Возвращает папку первого запускаемого вами скрипта. При желании вы можете указать переменную __file__ , но главное - вам не нужно совместно использовать эту переменную во всей иерархии вызовов .

Может быть, вы справитесь с другими сложными случаями, которых я не видел, но для меня это нормально.

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_))
Автор: hayj Размещён: 14.06.2016 03:06

0 плюса

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

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

Автор: Qiao Zhang Размещён: 12.04.2018 05:19

0 плюса

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

в 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>.

Автор: Lucas Azevedo Размещён: 08.06.2018 12:29

0 плюса

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

    import os
    base_directory = os.getcwd()
Автор: Ethan J. Размещён: 23.01.2019 04:31

0 плюса

Вот то, что я использую, чтобы я мог бросить свой код в любом месте без проблем. __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__))
Автор: craymichael Размещён: 28.06.2019 01:28

0 плюса

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

from pathlib import Path

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

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

current_path: Path = Path(__file__).parent.resolve()
Автор: Doug Размещён: 23.08.2019 07:19

-2 плюса

Большинство из этих ответов были написаны на 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
Автор: user3339488 Размещён: 09.11.2018 01:15

-3 плюса

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

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

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

Автор: sapam Размещён: 20.01.2013 08:52

-3 плюса

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)
Автор: jscabuzzo Размещён: 24.01.2013 02:43
Вопросы из категории :
32x32