Wie verwende ich inspect, um die Anruferinformationen von callee in Python abzurufen?

79

Ich muss die Anruferinformationen (welche Datei / welche Leitung) von Angerufenen erhalten. Ich habe gelernt, dass ich das Inpect-Modul dafür verwenden kann, aber nicht genau wie.

Wie bekomme ich diese Informationen mit inspect? Oder gibt es eine andere Möglichkeit, die Informationen zu erhalten?

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
quelle

Antworten:

98

Der Frame des Anrufers ist einen Frame höher als der aktuelle Frame. Sie können verwenden inspect.currentframe().f_back, um den Frame des Anrufers zu finden. Verwenden Sie dann inspect.getframeinfo , um den Dateinamen und die Zeilennummer des Anrufers abzurufen .

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
quelle
7
@prosseek: Um den Anrufer des Anrufers zu erhalten, ändern Sie einfach den Index [1]in [2]. ( inspect.getouterframesgibt eine Liste von Frames zurück ...). Python ist wunderschön organisiert.
Unutbu
3
Sie können auch inspect.currentframe (). F_back verwenden.
Yooy
Dies scheint keine Möglichkeit zu bieten, den vollständigen Pfad des Dateinamens abzurufen.
Jason S
2
@JasonS: "Der Dateiname im Stapelrahmen ist relativ zum Startverzeichnis der Anwendung".
Unutbu
2
Dieses Codebeispiel funktioniert, funktioniert aber ziemlich schlecht. Wenn Sie nur an einem einzelnen Frame und nicht an der gesamten Stapelverfolgung interessiert sind, können Sie den vorherigen Frame filename, line_number, clsname, lines, index = inspect.getframeinfo(sys._getframe(1))
abrufen
47

Ich würde vorschlagen, inspect.stackstattdessen zu verwenden :

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.
quelle
Wie ist es besser als getouterframeswie von @unutbu vorgeschlagen zu verwenden?
ixe013
8
Es ist kompakter und spiegelt die Absicht besser wider.
Dmitry K.
Beachten Sie, dass getouterframes(currentframe())und stack()unter der Haube github.com/python/cpython/blob/master/Lib/inspect.py#L1442
ubershmekel
1
Ein weiterer Grund für die Verwendung von stack () ist, dass es zeigt, wie einfach andere Frames abgerufen werden können. Wenn zum Beispiel. Ihre hello () -Funktion wird zuerst von einer anderen Funktion aufgerufen. Sie können sie aktualisieren, um zwei Ebenen zurück zu gehen.
Charles Plager
-5

Wenn der Aufrufer die Hauptdatei ist, verwenden Sie einfach sys.argv [0]

Jacob Cohen
quelle