2009-10-18 24 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"を2回呼びたいとは思わない。

スレッドセーフな別の方法がありますか? (私のアプリケーションでは、cProfileデータは、引数の1で指定されたデータファイルに保存されているので、それらは上書きされませんし、私は後でそれらを組み合わせることができます。)

答えて

26

私はあなたがこれを行うことができますことを発見:

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

欠点は、文書化されていないことです。

+2

ブリリアント!これは完璧に見えますが、 'datafn'とは何ですか? –

+0

@JonathanHartley - データファイルIIRCのファイル名。 – detly

+0

ああ、ありがとう。私は 'fn'はファイル名ではなく機能を意味すると考えた。 –

6

私は同じ問題を抱えていましたが、ラッパー関数を使用して直接戻り値を取得しました。代わりに

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

の私は、ラッパー関数

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

を作成し、アウトのparamから、fooの計算の結果を抽出するラッパー関数

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

への呼び出しをプロファイル(b)のその後。

+0

魅力的な作品です。 –

18

任意のコードのオプション:私は@detly .runcall()は基本的に最良の答えですが、完全を期すために、私はちょうど@ThomasHさんを撮りたかったと思いますhttps://docs.python.org/2/library/profile.html#profile.Profile

+0

'contextlib'の' contextmanager'デコレータを使ってコンテキストマネージャを少しでも作れます。 – detly

+0

「ランダムな注文が使用されました」が表示されます - どうすればリストの注文を指定できますか? –

+1

ps。sort_stats( 'cumulative') – marsh

1

から撮影

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

独立した機能であることを答える:

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 

をこれは、いくつかのマイナーな改善がありますこのページのその他の回答。