2009-10-18 37 views
15

我試圖來分析一個實例方法,所以我所做的是這樣的:返回值,而使用CPROFILE

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_actual」。我真的不想兩次調用「method_actual」。

有沒有另一種方式,可以線程安全的東西? (在我的應用程序中,CPROFILE數據保存到由args來命名一個數據文件,所以他們沒有得到打一頓,以後我可以將它們合併。)

回答

26

我發現,你可以這樣做:

prof = cProfile.Profile() 
retval = prof.runcall(self.method_actual, *args, **kwargs) 
prof.dump_stats(datafn) 

缺點是它沒有證件。

+2

太棒了!這看起來很完美 - 但'datafn'是什麼? – 2015-09-22 10:55:30

+0

@JonathanHartley - 數據文件IIRC的文件名。 – detly 2015-09-22 11:24:57

+0

啊,謝謝。我認爲'fn'是指函數,而不是文件名。 – 2015-09-22 14:12:27

6

我一直在努力解決同樣的問題,並使用包裝函數來獲取直接返回值。取而代之的

cP.runctx("a=foo()", globals(), locales()) 

我創建了一個包裝函數

def wrapper(b): 
    b.append(foo()) 

和配置文件調用的包裝函數

b = [] 
cP.runctx("wrapper(b)", globals(), locals()) 
a = b[0] 

提取了出來PARAM Foo的計算結果(B)之後。

+0

工程就像一個魅力。 – 2014-12-17 12:18:01

18

的任意代碼的選項:

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

+0

你甚至可以使用'contextlib'的'contextmanager'裝飾器爲它創建一個上下文管理器。 – detly 2013-06-23 09:46:15

+0

我得到'使用了隨機列表順序' - 我如何指定列表順序? – 2016-02-27 20:49:08

+1

ps。sort_stats( '累積') – marsh 2016-03-29 15:11:26

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

這是幾個小的改進其他答案在這個頁面上。