2012-08-03 15 views
7

Chcę uzyskać informacje o wywołujących określone funkcje w python. Na przykład:Uzyskaj informacje o funkcjach dzwoniących w pythonie

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." 

Czy to możliwe z pytonem?

Odpowiedz

10

Tak, funkcja sys._getframe() pozwala na pobieranie ramek z bieżącego stosu wykonawczego, które można następnie sprawdzić za pomocą metod i dokumentacji zawartych w inspect module; będziesz szukasz konkretnych mieszkańców w atrybucie f_locals, jak również za informacje f_code:

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

Należy pamiętać, że trzeba trochę uważać, aby wykryć, jakiego rodzaju informacje można znaleźć w każdej ramce.

+2

Od docs: 'To nie jest gwarantowana istnieć we wszystkich implementacjach Python.' – pradyunsg

3

Przykład:

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) 

odczyta "natychmiastowe" rozmówcę.

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

A jeśli nie została wywołana z innego dostać (w spoczynku):

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

Dziękuję Byłem w stanie to przyjąć i dostosować go do moich potrzeb. –

2

Dzięki Jon Clements odpowiedź udało mi się zrobić funkcję, która zwraca uporządkowaną listę wszystkich rozmówców:

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 

i kiedy nazywa się w łańcuchu:

def f2(): 
    return f1() 

def f3(): 
    return f2() 

def f4(): 
    return f3() 

print f4() 

wygląda następująco:

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

W moim przypadku odfiltrować niczego '<module>' i po, a następnie podjąć ostatnią pozycję, aby być nazwa dzwoniącego pochodzącymi.

lub zmodyfikować oryginalny pętlę ratować w pierwszej wygląd każdej nazwy rozpoczynające '<':

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