2012-08-03 13 views
7

Ich möchte Informationen über die Aufrufer einer bestimmten Funktion in Python erhalten. Zum Beispiel:Erhalten Funktion Anrufer Informationen in Python

class SomeClass(): 
    def __init__(self, x): 
     self.x = x 
    def caller(self): 
     return special_func(self.x) 

def special_func(x): 
    print "My caller is the 'caller' function in an 'SomeClass' class." 

Ist es mit Python möglich?

Antwort

10

Ja, mit der Funktion sys._getframe() können Sie Frames aus dem aktuellen Ausführungsstapel abrufen, die Sie dann mit den Methoden und der Dokumentation in der Datei inspect module überprüfen können. Sie werden in der f_locals Attribut für bestimmte Einheimischen suchen, sowie für die f_code Informationen:

import sys 
def special_func(x): 
    callingframe = sys._getframe(1) 
    print 'My caller is the %r function in a %r class' % (
     callingframe.f_code.co_name, 
     callingframe.f_locals['self'].__class__.__name__) 

Beachten Sie, dass Sie etwas zu kümmern brauchen, zu erkennen, welche Art von Informationen, die Sie in jedem Rahmen zu finden.

+2

Aus der Dokumentation: 'Es ist nicht in allen Implementierungen von Python.' garantiert existiert – pradyunsg

3

Ein Beispiel:

def f1(a): 
    import inspect 
    print 'I am f1 and was called by', inspect.currentframe().f_back.f_code.co_name 
    return a 

def f2(a): 
    return f1(a) 

Wird die "sofortige" Anrufer abzurufen.

>>> f2(1) 
I am f1 and was called by f2 

Und wenn nicht von einem anderen genannt wurde man (in IDLE) erhalten:

>>> f1(1) 
I am f1 and was called by <module> 
+0

Danke, Ich konnte dies übernehmen und an meine Bedürfnisse anpassen. –

2

Dank Jon Clements Antwort ich in der Lage war, eine Funktion zu machen, die eine geordnete Liste aller Anrufer zurückgibt:

def f1(): 
    names = [] 
    frame = inspect.currentframe() 
    ## Keep moving to next outer frame 
    while True: 
     try: 
      frame = frame.f_back 
      name = frame.f_code.co_name 
      names.append(name) 
     except: 
      break 
    return names 

und wenn in einer Kette genannt:

def f2(): 
    return f1() 

def f3(): 
    return f2() 

def f4(): 
    return f3() 

print f4() 

sieht wie folgt aus:

['f2', 'f3', 'f4', '<module>'] 

In meinem Fall habe ich überhaupt etwas '<module>' herauszufiltern und nach, und dann das letzte Element nehmen den Namen des Ursprungs Anrufer sein.

oder die ursprüngliche Schleife ändert beim ersten Auftreten von einem beliebigen Namen mit '<' beginnen zu retten:

frame = frame.f_back 
name = frame.f_code.co_name 
if name[0] == '<': 
    break 
names.append(name)