跟踪Python中调用内置函数的位置
当我使用跟踪Python中调用内置函数的位置,python,debugging,Python,Debugging,当我使用cProfile一个程序时,我发现我花了很多时间打昂贵的zip电话。我编写的代码没有进行这些zip调用,所以它一定是我从导入的许多库中引入的代码 有没有一个工具可以让我标记一个函数调用,并告诉我哪些函数在Python中调用了该函数?不久前,我遇到了一个类似于您的问题,我设法解决了它。这不是一个工具,但可能对你有用。只需将以下代码放在主模块的顶部 注意:该代码是为您所需的zip功能定制的,对我来说它可以工作(当然还有另一个功能,我现在不记得它的名字了)。我额外导入的是我应用程序中的第三方模
cProfile
一个程序时,我发现我花了很多时间打昂贵的zip
电话。我编写的代码没有进行这些zip调用,所以它一定是我从导入的许多库中引入的代码
有没有一个工具可以让我标记一个函数调用,并告诉我哪些函数在Python中调用了该函数?不久前,我遇到了一个类似于您的问题,我设法解决了它。这不是一个工具,但可能对你有用。只需将以下代码放在主模块的顶部 注意:该代码是为您所需的
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)
(,'/home/user/untitled4.py',17,'test',['zip([1,2],[3,4])\n'],0)
(,'/home/user/untitled4.py',20',,['zip([1,2],[3,4])\n'],0)
A实现所需功能的快捷方法非常简单:用自定义功能替换内置的zip
[8]中的:导入检查
在[9]中:定义my_zip(*iterables):
…:frame=inspect.currentframe().f_back
…:my_zip.callees.append(frame.f_code.co_name)
…:返回我的拉链。旧拉链(*iterables)
在[10]:my_zip.callees=[]
在[11]中:my_-zip.old_-zip=zip
在[12]中:导入内置项
在[13]中:builtins.zip=my_-zip
In[14]:zip(范围(5),范围(4))
出[14]:
在[15]:zip.callees中,在模块级调用。。。
Out[15]:['']
(在python2中,将内置
模块替换为内置
)
更智能的实现将使用collections.Counter
,并避免保留调用zip
的所有函数名的列表
但是,您可能需要知道的不仅仅是zip
的呼叫者的姓名。也许还有另一个函数f
调用g
调用h
调用zip
,但是要知道f
是问题的真正原因,你必须以某种方式将h
和f
联系起来
扩展my_-zip
以跟踪更多信息应该不难
然而,我相信
cProfile
的输出应该提供足够的时间信息,以便或多或少地理解zip
的调用位置。您尤其应该仔细研究其输出的cumtime
列
您还应该考虑调用函数的次数。通常一个函数在被调用时总是执行相同数量的zip
s,因此对zip
和“罪魁祸首”函数的调用次数在某种程度上应该是成比例的
当然,隐藏这些关系的噪音可能很多,但你应该试着弄清楚 您可以从探查器输出中获取该信息。从输出创建一个对象并调用
stats.print\u调用者('zip')
这应该向您显示调用它的函数,以及每个调用方调用它的次数,以及调用中花费的总时间和累计时间。我相信
cProfile
的输出已经为您提供了在函数累计成本中“隐藏”的信息。提供cProfile
的输出会很有帮助。
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>']