Jak używać inspect, aby uzyskać informacje o dzwoniącym od wywołującego w Pythonie?


80

Muszę uzyskać informacje o dzwoniącym (jaki plik / jaka linia) od dzwoniącego. Dowiedziałem się, że mogę użyć do tego modułu inpect, ale nie do końca.

Jak zdobyć te informacje podczas inspekcji? Czy jest inny sposób na uzyskanie informacji?

import inspect

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

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

hello()

Odpowiedzi:


99

Ramka wywołującego jest o jedną ramkę wyższa niż bieżąca ramka. Możesz użyć, inspect.currentframe().f_backaby znaleźć ramkę dzwoniącego. Następnie użyj inspect.getframeinfo, aby uzyskać nazwę pliku dzwoniącego i numer linii.

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: Aby uzyskać rozmówcę dzwoniącego, po prostu zmień indeks [1]na [2]. ( inspect.getouterframeszwraca listę ramek ...). Python jest pięknie zorganizowany.
unutbu

3
Możesz także użyć inspect.currentframe (). F_back.
jojo

Wydaje się, że nie zapewnia to sposobu na uzyskanie pełnej ścieżki nazwy pliku.
Jason S

2
@JasonS: "nazwa pliku w ramce stosu jest określana względem katalogu startowego aplikacji".
unutbu

4
Ten przykładowy kod działa, ale działa dość słabo. Jeśli interesuje Cię tylko pojedyncza ramka, a nie cały ślad stosu, możesz pobrać poprzednią klatkę i sprawdzić ją pod kątem informacji o klatce: filename, line_number, clsname, lines, index = inspect.getframeinfo(sys._getframe(1))
Mouscellaneous

47

Sugerowałbym inspect.stackzamiast tego użyć :

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

Jak to jest lepsze niż używanie getouterframessugerowane przez @unutbu?
ixe013

8
Jest bardziej zwarty i lepiej odzwierciedla zamiar.
Dmitry K.

Zauważ, że getouterframes(currentframe())i stack()są równoważne pod maską github.com/python/cpython/blob/master/Lib/inspect.py#L1442
ubershmekel

1
Innym powodem używania stack () jest to, że pokazuje, jak łatwo uzyskać inne ramki. Jeśli na przykład. Twoja funkcja hello () jest najpierw wywoływana przez inną funkcję, możesz ją zaktualizować, aby cofnąć się o dwa poziomy.
Charles Plager


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.