跟踪在Python中调用内置函数的位置

时间:2013-12-30 18:40:42

标签: python debugging

当我cProfile我正在开展的一项计划时,我发现我花了很多时间拨打昂贵的zip电话。我写的代码不是这些zip调用,所以它必须是我从我导入的许多库中的一个引入的代码。

是否有一个工具可以让我标记一个函数调用,并告知哪些函数在Python中调用了该函数?

3 个答案:

答案 0 :(得分:4)

您可以从探查器输出中获取该信息。从输出中创建Stats对象并调用stats.print_callers('zip')

这应该显示调用它的函数,以及每个调用者调用它的次数以及调用中花费的总时间和累计时间。

答案 1 :(得分:0)

前段时间我遇到了像你这样的问题,我设法解决了这个问题。它不是工具,但可能对您有用。只需将以下代码放在主模块的顶部即可。

注意:代码是为您需要的zip功能量身定制的,对我来说它是有效的(当然对于另一个功能,我现在不记得名字)。我做的额外导入是我的应用程序中的第三方模块,我不知道它是否适用于标准库中的模块。

import inspect

def trackZip(*args):
    print inspect.getouterframes(inspect.currentframe())[1]
    return __builtins__.zip(*args)

zip = trackZip

#do more imports...

def test():
    zip([1,2],[3,4])

test()
zip([1,2],[3,4])

<强>输出:

(<frame object at 0x1948260>, '/home/user/untitled4.py', 17, 'test', ['    zip([1,2],[3,4])\n'], 0)
(<frame object at 0x11fd3d0>, '/home/user/untitled4.py', 20, '<module>', ['zip([1,2],[3,4])\n'], 0)

答案 2 :(得分:0)

快速&amp;实现你想要的东西很简单:用自定义函数替换内置的zip

In [8]: import inspect
In [9]: def my_zip(*iterables):
   ...:     frame = inspect.currentframe().f_back
   ...:     my_zip.callees.append(frame.f_code.co_name)
   ...:     return my_zip.old_zip(*iterables)

In [10]: my_zip.callees = []

In [11]: my_zip.old_zip = zip

In [12]: import builtins

In [13]: builtins.zip = my_zip

In [14]: zip(range(5), range(4))
Out[14]: <builtins.zip at 0x7f06a2324290>

In [15]: zip.callees  # called at module level...
Out[15]: ['<module>']

(在python2中用builtins替换__builtin__模块。)

更智能的实现将使用collections.Counter并避免保留名为zip的所有函数名列表。

但是,您可能需要了解zip来电者的姓名。也许有一个其他函数f调用g来调用调用h的{​​{1}},但要告诉zip是导致问题的真正原因以某种方式关联fh

不应该扩展f来跟踪更多信息。


然而,我相信my_zip的输出应提供足够的时序信息,或多或少地了解调用cProfile的位置。特别是你应该仔细研究其输出的zip列。

您还应该考虑调用函数的次数。通常,一个函数在被调用时总会执行相同数量的cumtime s,因此调用zip和&#34;罪魁祸首&#34;功能应该在某种程度上成比例。

肯定会有很多噪音隐藏这些关系,但你应该试着弄明白。