Получить абсолютный путь вызывающей функции к ее файлу?

Если в файле t1 есть метод a.py и есть файл b.py, который вызывает метод t1 из a.py файла. Как получить полный/абсолютный путь к файлу b.py внутри метода t1?

С помощью модуля проверки (как здесь: как получить имя файла вызывающего абонента, имя метода в python) я могу получить относительный путь к файлу, но, похоже, он не содержит абсолютного пути (или есть какой-то другой объект атрибута, к которому можно получить доступ?).

Например:

а.py:

def t1():
    print('callers absolute path')

б.пи:

from a import t1
t1()  # should print absolute path for `b.py`

Разве t1() не должен возвращать абсолютный путь для a.py?

DirtyBit 02.04.2019 09:51

Итак, вы спрашиваете, как превратить относительный путь в абсолютный...?

Aran-Fey 02.04.2019 09:51

@DirtyBit нет. Чтобы получить путь a.py, вы просто используете __file__ или sys.path[0]. Но мне нужен путь вызывающего абонента, а не путь вызываемого метода.

Andrius 02.04.2019 09:55

@Aran-Fey Если он не возвращает абсолютный путь, то да. Интересно, будет ли использование комбинации с os.path.realpath всегда возвращать правильный абсолютный путь? Причина Функция realpath объединяет текущий рабочий каталог с относительным путем.

Andrius 02.04.2019 09:57
__file__ всегда является допустимым путем, то есть да, он относится к текущему рабочему каталогу. (Если вы не изменили CWD в своем коде, но тогда это ваша вина...)
Aran-Fey 02.04.2019 09:58
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
5
1 241
5

Ответы 5

Вы можете получить его с помощью модуля os в Python.

>>> import a
>>> os.path.abspath(a.__file__)

Это даст вам путь к текущему файлу, а не к файлу вызывающих абонентов.

Andrius 02.04.2019 09:58

С помощью модуля os вы можете сделать следующее:

а.ру

import os

def t1(__file__):
    print(os.path.abspath(__file__))

б.пи

from a import t1
t1(__file__)  # shoult print absolute path for `b.py`

При этом вы можете вызвать t1(__file__ и получить абсолютный путь для любого файла.

Я знаю, но это не то, что мне нужно. Мне нужно получить этот путь внутри a.py. Обеспечить это должно быть задачей a.py, а не b.py.

Andrius 02.04.2019 10:00

печать (os.path.abspath («b.py»))

Mikkel Madsen 02.04.2019 10:10

Ну, вам все еще нужно указать имя файла вызывающего абонента, так что ничего хорошего :)

Andrius 02.04.2019 10:13
import os
import inspect


def get_cfp(real: bool = False) -> str:
    """Return caller's current file path.

    Args:
        real: if True, returns full path, otherwise relative path
            (default: {False})
    """
    frame = inspect.stack()[1]
    p = frame[0].f_code.co_filename
    if real:
        return os.path.realpath(p)
    return p

Запуск из другого модуля:

from module import my_module
p1 = my_module.get_cfp()
p2 = my_module.get_cfp(real=True)
print(p1)
print(p2)

Отпечатки:

test_path/my_module_2.py
/home/user/python-programs/test_path/my_module_2.py

Использование sys._getframe():

a1.py:

import sys
def t1():
    print(sys._getframe().f_code)

a2.py:

from a1 import t1
t1()  # should print absolute path for `b.py`

Следовательно:

py -m a2.py

ВЫХОД:

<code object t1 at 0x0000029BF394AB70, file "C:\Users\dirtybit\PycharmProjects\a1.py", line 2>

РЕДАКТИРОВАТЬ:

Использование inspect:

a1.py:

import inspect
def t1():
    print("Caller: {}".format(inspect.getfile(inspect.currentframe())))

a2.py:

from a1 import t1
t1()  # should print absolute path for `b.py`

ВЫХОД:

Caller: C:\Users\dirtybit\PycharmProjects\a1.py

Хитрость заключается в восстановлении как текущего рабочего каталога а также, так и относительного пути относительно этого каталога к вызывающему файлу (здесь b.py). Объединение делает все остальное.

а.py:

    import os
    import sys
    def t1():
        namespace = sys._getframe(1).f_globals
        cwd = os.getcwd()
        rel_path = namespace['__file__']
        abs_path= os.path.join(cwd,rel_path)
        print('callers absolute path!',abs_path)

б.пи:

    from a import t1
    t1()  # prints absolute path for `b.py`

Трюк не работает для ноутбуков Jupyter, к сожалению.

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