在python中获取函数调用者的信息

时间:2012-08-03 16:02:56

标签: python introspection callstack

我想获得有关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."

是否可以使用python?

3 个答案:

答案 0 :(得分:11)

是的,sys._getframe()函数允许您从当前执行堆栈中检索帧,然后您可以使用inspect module中的方法和文档进行检查;您将在f_locals属性以及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__)

请注意,您需要注意检测每个帧中找到的信息类型。

sys._getframe()返回一个框架对象,您可以按照每个框架上的f_back引用链接整个堆栈。或者,您可以使用inspect.stack() function生成包含其他信息的框架列表。

答案 1 :(得分:3)

一个例子:

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)

将检索“立即”呼叫者。

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

如果没有从另一个人那里得到你(在IDLE中):

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

答案 2 :(得分:2)

感谢Jon Clements的回答,我能够创建一个返回所有呼叫者的有序列表的函数:

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

并在链中调用时:

def f2():
    return f1()

def f3():
    return f2()

def f4():
    return f3()

print f4()

看起来像这样:

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

在我的情况下,我会在'<module>'及之后过滤掉任何内容,然后将最后一项作为原始来电者的名称。

或者在首次出现以'<'开头的任何名称时修改原始循环以保释:

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