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()
prosseek
źródło

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)
unutbu
źródło
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()
Dmitry K.
źródło
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
-5

Jeśli dzwoniącym jest główny plik, po prostu użyj sys.argv [0]

Jacob Cohen
źródło