我正在尝试分析实例方法,所以我做了类似的事情:
import cProfile
class Test():
def __init__(self):
pass
def method(self):
cProfile.runctx("self.method_actual()", globals(), locals())
def method_actual(self):
print "Run"
if __name__ == "__main__":
Test().method()
但是现在当我希望“method”返回由“method_actual”计算的值时出现问题。我真的不想两次打电话给“method_actual”。
还有其他方式,可以线程安全吗? (在我的应用程序中,cProfile数据被保存到由其中一个args命名的数据文件中,因此它们不会被破坏,我可以在以后组合它们。)
答案 0 :(得分:34)
我发现你可以这样做:
prof = cProfile.Profile()
retval = prof.runcall(self.method_actual, *args, **kwargs)
prof.dump_stats(datafn)
缺点是它没有记录。
答案 1 :(得分:20)
任意代码的选项:
import cProfile, pstats, sys
pr = cProfile.Profile()
pr.enable()
my_return_val = my_func(my_arg)
pr.disable()
ps = pstats.Stats(pr, stream=sys.stdout)
ps.print_stats()
取自https://docs.python.org/2/library/profile.html#profile.Profile
答案 2 :(得分:6)
我正在努力解决同样的问题并使用包装函数来克服直接返回值。而不是
cP.runctx("a=foo()", globals(), locales())
我创建了一个包装函数
def wrapper(b):
b.append(foo())
并分析对包装函数的调用
b = []
cP.runctx("wrapper(b)", globals(), locals())
a = b[0]
之后从out参数(b)中提取foo计算的结果。
答案 3 :(得分:1)
我认为@detly .runcall()
基本上是最好的答案,但为了完整起见,我只想将@ThomasH的答案视为功能独立:
def wrapper(b, f, *myargs, **mykwargs):
try:
b.append(f(*myargs, **mykwargs))
except TypeError:
print 'bad args passed to func.'
# Example run
def func(a, n):
return n*a + 1
b = []
cProfile.runctx("wrapper(b, func, 3, n=1)", globals(), locals())
a = b[0]
print 'a, ', a
答案 4 :(得分:1)
我创建了一个装饰者:
import cProfile
import functools
import pstats
def profile(func):
@functools.wraps(func)
def inner(*args, **kwargs):
profiler = cProfile.Profile()
profiler.enable()
try:
retval = func(*args, **kwargs)
finally:
profiler.disable()
with open('profile.out', 'w') as profile_file:
stats = pstats.Stats(profiler, stream=profile_file)
stats.print_stats()
return retval
return inner
用它装饰你的功能或方法:
@profile
def somefunc(...):
...
现在该功能将被分析。
或者,如果你想要原始的,未经处理的配置文件数据(例如,因为你想在其上运行优秀的图形查看器RunSnakeRun),那么:
import cProfile
import functools
import pstats
def profile(func):
@functools.wraps(func)
def inner(*args, **kwargs):
profiler = cProfile.Profile()
profiler.enable()
try:
retval = func(*args, **kwargs)
finally:
profiler.disable()
profiler.dump_stats('profile.out')
return retval
return inner
这是对本页其他几个答案的一个小改进。