使用cProfile时返回值

时间:2009-10-18 09:04:26

标签: python

我正在尝试分析实例方法,所以我做了类似的事情:

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命名的数据文件中,因此它们不会被破坏,我可以在以后组合它们。)

5 个答案:

答案 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

这是对本页其他几个答案的一个小改进。