【发布时间】:2019-01-14 22:16:37
【问题描述】:
我有一个 C++ 库,我正在通过 python 包装和公开它。由于各种原因,我需要在通过 python 公开它们时重载函数的__call__。
下面是一个使用time.sleep 模拟具有不同计算时间的函数的最小示例
import sys
import time
class Wrap_Func(object):
def __init__(self, func, name):
self.name = name
self.func = func
def __call__(self, *args, **kwargs):
# do stuff
return self.func(*args, **kwargs)
def wrap_funcs():
thismodule = sys.modules[__name__]
for i in range(3):
fname = 'example{}'.format(i)
setattr(thismodule, fname, Wrap_Func(lambda: time.sleep(i), fname))
wrap_funcs()
通过cProfile 分析我的代码时,我得到了__call__ 例程的列表。
我无法确定哪些例程占用了大部分计算时间。
>>> import cProfile
>>> cProfile.runctx('example0(); example1(); example2()', globals(), locals())
11 function calls in 6.000 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
3 0.000 0.000 6.000 2.000 <ipython-input-48-e8126c5f6ea3>:11(__call__)
3 0.000 0.000 6.000 2.000 <ipython-input-48-e8126c5f6ea3>:20(<lambda>)
1 0.000 0.000 6.000 6.000 <string>:1(<module>)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
3 6.000 2.000 6.000 2.000 {time.sleep}
预期
通过手动定义函数(这需要是动态的和上面的包装器)为
def example0():
time.sleep(0)
def example1():
time.sleep(1)
def example2():
time.sleep(2)
我得到了预期的输出
>>> import cProfile
>>> cProfile.runctx('example0(); example1(); example2()', globals(), locals())
11 function calls in 6.000 seconds
8 function calls in 3.000 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.000 0.000 <ipython-input-58-688d247cb941>:1(example0)
1 0.000 0.000 0.999 0.999 <ipython-input-58-688d247cb941>:4(example1)
1 0.000 0.000 2.000 2.000 <ipython-input-58-688d247cb941>:7(example2)
1 0.000 0.000 3.000 3.000 <string>:1(<module>)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
3 3.000 1.000 3.000 1.000 {time.sleep}
【问题讨论】:
-
注意this 不起作用,因为它需要能够被通用调用
-
查看
cProfile.Profiler.snapshot_stats似乎问题的根源在于__call__.func_code.co_name
标签: python-2.7 monkeypatching cprofile