Как использовать 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)

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вызывающий абонент и т. д.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.