Как использовать inspect для получения информации о вызывающем абоненте от вызываемого в Python?

80

Мне нужно получить информацию о вызывающем абоненте (какой файл / какая строка) от вызываемого абонента. Я узнал, что могу использовать для этого модуль inpect, но не совсем как.

Как получить эту информацию с помощью inspect? Или есть другой способ получить информацию?

import inspect

print __file__
c=inspect.currentframe()
print c.f_lineno

def hello():
    print inspect.stack
    ?? what file called me in what line?

hello()
просек
источник

Ответы:

99

Кадр вызывающего абонента на один кадр выше текущего кадра. Вы можете использовать inspect.currentframe().f_backдля поиска кадра звонящего. Затем используйте inspect.getframeinfo, чтобы получить имя файла вызывающего абонента и номер строки.

import inspect

def hello():
    previous_frame = inspect.currentframe().f_back
    (filename, line_number, 
     function_name, lines, index) = inspect.getframeinfo(previous_frame)
    return (filename, line_number, function_name, lines, index)

print(hello())

# ('/home/unutbu/pybin/test.py', 10, '<module>', ['hello()\n'], 0)
Unutbu
источник
7
@prosseek: чтобы получить вызывающего абонента, просто измените индекс [1]на [2]. ( inspect.getouterframesвозвращает список кадров ...). Python прекрасно организован.
unutbu
3
Вы также можете использовать inspect.currentframe (). F_back.
йойо
Кажется, это не дает возможности получить полный путь к имени файла.
Jason S
2
@JasonS: "имя файла в кадре стека соответствует стартовому каталогу приложения".
unutbu 02
4
Этот пример кода работает, но работает довольно плохо. Если вас интересует только один кадр, а не вся трассировка стека, вы можете получить предыдущий кадр и проверить его на наличие информации о кадре: filename, line_number, clsname, lines, index = inspect.getframeinfo(sys._getframe(1))
Mouscellaneous
47

Я бы предложил inspect.stackвместо этого использовать :

import inspect

def hello():
    frame,filename,line_number,function_name,lines,index = inspect.stack()[1]
    print(frame,filename,line_number,function_name,lines,index)
hello()
Дмитрий К.
источник
Чем это лучше, чем использовать, getouterframesпредложенный @unutbu?
ixe013 04
8
Он более компактный и лучше отражает замысел.
Дмитрий К.
Обратите внимание, что getouterframes(currentframe())и stack()под капотом эквивалентны github.com/python/cpython/blob/master/Lib/inspect.py#L1442
ubershmekel
1
Еще одна причина, по которой использование stack () приятно, состоит в том, что он показывает, как легко получить другие кадры. Если, например. ваша функция hello () сначала вызывается другой функцией, вы можете обновить ее, чтобы вернуться на два уровня назад.
Чарльз Плагер
2

Я опубликовал оболочку для проверки с простой адресацией стекового фрейма, покрывающей фрейм стека одним параметром spos:

Например pysourceinfo.PySourceInfo.getCallerLinenumber(spos=1)

где spos=0- функция библиотеки, spos=1- вызывающий абонент, spos=2вызывающий абонент и т. д.

острый
источник
-5

Если вызывающий - главный файл, просто используйте sys.argv [0]

Джейкоб Коэн
источник