Get function callers info in python

I want to get information about callers of a specific function in python. For example:

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

Is this possible with python?

+7
source share
3 answers

Yes, sys._getframe() allows you to retrieve frames from the current execution stack, which can then be checked using the methods and documentation found in the inspect module ; You will look for specific f_locals attribute f_locals , as well as information about 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__) 

Please note that you need to take care to determine what information you find in each frame.

sys._getframe() returns a frame object, you can f_back entire stack by following the f_back link for each. Or you can use inspect.stack() to create frame lists with additional information.

+10
source

Example:

 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) 

Retrieves the "immediate" caller.

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

And if it was not called from another, you get (in IDLE):

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

Thanks to John Clement's answer, I was able to create a function that returns an ordered list of all callers:

 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 

and when called in the chain:

 def f2(): return f1() def f3(): return f2() def f4(): return f3() print f4() 

looks like that:

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

In my case, I filter out something in '<module>' and after, and then take the last element as the name of the caller.

Or, change the source loop to pledge the first time any name starting with '<' appears:

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

All Articles