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

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

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

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

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

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

Связанный: Атрибут Python __file__ абсолютный или относительный?

kenorb 20.05.2015 23:15

os.path.realpath (файл)

Girish Gupta 16.04.2017 07:40
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
500
3
554 111
29
Перейти к ответу Данный вопрос помечен как решенный

Ответы 29

Не совсем понятно, что вы подразумеваете под «путем к файлу, который в данный момент выполняется в процессе». 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]! :) а ты только имя узнаешь!

aF. 01.09.2011 19:02

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

Аааа ... execfile - это сложно. См. Другой мой пост об использовании модуля проверки.

Pat Notz 09.09.2008 03:03

Атрибут __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()), он дает мне полный путь к обрабатываемому файлу. Поэтому я не уверен, что вы имеете в виду или при каких условиях это не дало бы «имя и путь».

LarsH 29.01.2013 22:55

Оно делает? Не для меня и еще нескольких, судя по всему. Вторая строка, которая была добавлена ​​к ответу, дает полный путь, хотя

David Sykes 30.01.2013 17:02

ВНИМАНИЕ: этот вызов не дает одинакового результата в разных средах. Вы можете принять ответ Усаги ниже: stackoverflow.com/a/6628348/851398

faraday 05.03.2014 11:41

@faraday: Не могли бы вы привести пример? Я ответил аналогичный вопрос с использованием inspect.getabsfile(), и он работал во всех случаях, которые я пробовал.

jfs 05.04.2014 21:04

Действительно ли @Usagi отвечает лучше?

Dror 23.12.2014 13:13

нет, user13993 прибил это намного лучше

osirisgothra 13.08.2015 07:49

user13993 действительно пригвоздил. Должен быть os.path.realpath(__file__)

uchuugaka 13.08.2015 12:02

Метод @Dror user13933 дает мне имя вызывающего, а не вызываемого. Это правильно для заданного вопроса.

blindguy 11.09.2015 23:54

@osirisgothra: вы понимаете, что __file__ не работает с execfile(), который упоминается в вопросе явно.

jfs 21.09.2015 20:20

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

emish 18.12.2015 01:49

inspect.getfile() возвращает атрибут __file__, если передан объект модуля. inspect.currentframe() возвращает модуль. Ergo, это дорогой способ сказать __file__.

Martijn Pieters 12.05.2018 22:01

Вы можете использовать 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». Так что выход нестабилен.

mechatroner 06.09.2015 02:53

Но поскольку мы используем только путь к этому файлу, это не имеет значения.

Uwe Koloska 29.09.2016 12:36

это странно: при запуске из командной строки "__file__" в кавычках (как строка) дает каталог, из которого запускается cmd, но __file__ (без кавычек дает путь к исходному файлу ... почему это

muon 09.05.2018 16:53

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

Jamie Bull 26.10.2018 11:11

import sys

print sys.path[0]

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

sys.path [0] очень полезен, но дает путь к сценарию 1, а не к сценарию 3, как было запрошено.

James 28.01.2011 04:26

По крайней мере, на OS X с 2.7 я не считаю, что это что-то надежное. Он работает, если запускать один и тот же файл напрямую. Не работает репл, особенно от импортного яйца

uchuugaka 13.08.2015 11:58

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

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

hayj 14.06.2016 17:29

На самом деле это дорогостоящий способ написания sys.modules['__main__'].__file__.

Martijn Pieters 12.05.2018 22:08

import sys
print sys.argv[0]

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

cregox 13.05.2010 21:40

Я использовал подход с __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] приведет вас к нижней части стека, к исходному сценарию вызова.

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

jpmc26 19.01.2018 05:13

inspect.getfile() возвращает атрибут __file__, если передан объект модуля. inspect.currentframe() возвращает модуль. Ergo, это дорогой способ сказать __file__.

Martijn Pieters 12.05.2018 22:01

inspect.stack() - довольно дорогая функция, больше, чем просто inspect.currentframe(), и она также вызывает inspect.getfile() для объекта модуля.

Martijn Pieters 12.05.2018 22:03

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

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

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

Для этого мне пришлось «импортировать os, sys», но пока это лучший ответ, который фактически возвращает только путь без имени файла в конце строки.

emmagras 18.10.2014 19:40

если вам нужно только имя файла без ./ или .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 (файл), как было предложено выше.

samaspin 22.05.2015 17:17

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) отличается от каталога, в котором находится файл.

Iron Pillow 02.08.2014 00:59

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

Michael Mior 13.08.2014 05:39

@IronPillow, возможно, этот ответ поможет вам с тем, что вам нужно. stackoverflow.com/a/41546830/3123191

Kwuite 23.02.2017 18:21

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

hlin117 25.04.2015 20:51

В Python3 os.path.dirname предоставит вам относительный путь, откуда вы запускаете скрипт. например в python ../../test.pyos.path.dirname будет ../../, а не абсолютным путем к сценарию. Я искал abspath, но удалял название скрипта. Очевидно, первым элементом sys.path является ответ sys.path[0].

aerijman 13.11.2019 17:42

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

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('\','/')

Это не правильно. Это даст вам текущий путь, но не путь к текущему файлу.

Charles Plager 10.10.2018 16:09

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

в 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()

Не могли бы вы изменить свой ответ так, чтобы он относился к заданному вопросу? Этот ответ не относится к вопросу «Как мне получить путь и имя файла, который выполняется в данный момент?»

Marco 14.03.2019 19:17

Это дает путь, по которому вы запустили команду python. Таким образом, кажется, что это работает, когда вы запускаете команду python script.py в той же папке, в которой вы уже находитесь, хотя на самом деле это то же самое, что запускать pwd в Linux.

George 14.07.2019 16:10

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

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

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

Ответы только на код не приветствуются. Пожалуйста, объясните, как это решает проблему или чем это отличается от существующих ответов. Из обзора

Nick 05.05.2019 04:51

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

Другие вопросы по теме