查找python内置函数的调用者

时间:2019-09-12 16:11:05

标签: python cprofile

这类似于Profiling in Python: Who called the function? ,但有所不同。。我有一个使用cProfile进行分析的python函数。在我的首次运行中,统计数据显示,它大部分时间都花在%(FooterContent)的{​​{1}}中;

好的,我在系统上找到了get_loc()文件,并在datetimes.py的顶部临时添加了datetimes.pyimport pdb,然后随机使用了调试器命令{{1} }多次,并且pdb.set_trace()之间的随机数为get_loc()。这告诉我,根据我的随机样本,几乎所有where的数千次调用最终都来自我自己代码中的同一位置。我修改了该代码以大大减少调用次数。太好了!

接下来,我现在看到在对continue超过66,000 个调用中花费了大量时间;问题是我找不到实现堆栈跟踪的源代码,无法找出正在调用的where。 (根据我对Python的有限知识,我正在猜测,实际上get_loc()是直接或通过共享对象链接到Python解释器的C代码)。无论如何,我找不到所谓的builtins.isinstance()。我尝试了在Profiling in Python: Who called the function? 的答案中也发现的 Gprof2dot 方法,但这仅显示isinstance()正在被isinstance和调用图调用在isinstance停在那里。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

我已经做了一些挖掘工作,并将至少部分地尝试回答我的问题(希望其他人能够看到并贡献出更多关于如何使之变得容易的想法)。

这就是我配置函数的方式

pr = cProfile.Profile()                # create a cProfiler object 
pr.enable()                            # turn profiling on
pr.runcall( myfunc, arg1, arg2, ... )  # profile my function
pr.disable()                           # turn profiling off

然后,这是找到呼叫者的关键:

import pstats
p = pstats.Stats(pr)           # create pstats obj based on profiler above.
p.print_callers('isinstance')  # find all the callers of isinstance.

print_callers函数可打印出isinstance的130个呼叫者,以及每个呼叫者呼叫isinstance的次数。需要消化很多东西,但是出于分析的目的,将注意力集中在调用最多的几个上并找到他们的调用者是有意义的。这是列表的一部分(print_callers或多或少地以随机顺序显示,但是我已经根据调用次数对它们进行了排序)...

Function {built-in method builtins.isinstance} was called by...
                                           ncalls  tottime  cumtime
                                             2808    0.002    0.002  /anaconda3/lib/python3.7/site-packages/pandas/core/indexes/datetimes.py:974(get_loc)
                                             2158    0.006    0.018 /anaconda3/lib/python3.7/site-packages/pandas/core/dtypes/base.py:75(is_dtype)
                                             2030    0.001    0.001  /anaconda3/lib/python3.7/site-packages/pandas/core/dtypes/common.py:1845(_is_dtype_type)
                                             1930    0.001    0.001  /anaconda3/lib/python3.7/site-packages/pandas/core/dtypes/common.py:1981(pandas_dtype)
                                             1440    0.001    0.001  /anaconda3/lib/python3.7/site-packages/pandas/core/dtypes/dtypes.py:68(find)
                                             1058    0.001    0.001  /anaconda3/lib/python3.7/site-packages/pandas/core/indexes/datetimes.py:924(get_value)
                                              841    0.000    0.000  /anaconda3/lib/python3.7/site-packages/pandas/core/dtypes/common.py:1809(_get_dtype)
                                              726    0.000    0.000  /anaconda3/lib/python3.7/site-packages/pandas/core/dtypes/common.py:1702(is_extension_arr
...
                                                6    0.000    0.000  /anaconda3/lib/python3.7/site-packages/pandas/core/indexing.py:153(_get_setitem_indexer)
                                                5    0.000    0.000  /anaconda3/lib/python3.7/site-packages/pandas/core/ops.py:1660(wrapper)
                                                5    0.000    0.000  /anaconda3/lib/python3.7/site-packages/pandas/core/ops.py:1447(_align_method_SERIES)
                                                5    0.000    0.000 /anaconda3/lib/python3.7/site-packages/pandas/core/computation/expressions.py:163(_has_bool_dtype)
                                                4    0.000    0.000 /anaconda3/lib/python3.7/site-packages/pandas/core/internals/blocks.py:3100(_extend_blocks)
                                                4    0.000    0.000  /anaconda3/lib/python3.7/site-packages/pandas/core/indexing.py:2501(check_setitem_lengths)
                                                3    0.000    0.000  /anaconda3/lib/python3.7/site-packages/pandas/core/indexes/base.py:566(_shallow_copy)
                                                3    0.000    0.000  /anaconda3/lib/python3.7/site-packages/pandas/core/dtypes/common.py:702(is_datetimelike)
                                                3    0.000    0.000  /anaconda3/lib/python3.7/posixpath.py:41(_get_sep)
                                                2    0.000    0.000  /anaconda3/lib/python3.7/distutils/version.py:331(_cmp)

在这一点上,我想我可以单调乏味地浏览最大的调用者(找到最大的调用者,依此类推)或编写脚本来做到这一点。将继续进行挖掘,并在以后发布其他进度。