プロファイリングを乱雑にしているのはデコレータ自体ではなく、デコレータによって作成されたラッパー関数であると推測します。そして、それはすべてのラッパー関数が同じ名前を持っているために起こっています。これに対処するには、デコレータにラッパー関数の名前を変更させるだけです。
def decorator(func):
def wrapper(*args):
print "enter func", func.__name__
return func(*args)
wrapper.__name__ += "_" + func.__name__
return wrapper
を使用することもできますがfunctools.wraps()、ラッパー関数の名前は、ラップしている関数の名前と一致します。プロファイリングは大丈夫だと思います。
これで、関数のコードオブジェクトにも名前が付けられました。Pythonはスタック上の関数への参照を保存せず、コードオブジェクトのみを保存するため、プロファイラーがスタックフレームからラッパー関数の名前を取得している場合は、この名前を取得します。通常の方法で定義されたラッパーは、各ラッパー関数のコードオブジェクトと関数オブジェクトを明示的に再構築しない限り、コードオブジェクトを共有します(関数オブジェクトは異なります)。これはかなり多くの作業であり、CPython固有です(バージョン固有の場合もあります)。しかし、これがあなたがそれについて行くかもしれない方法です:
from types import FunctionType, CodeType
def decorator(func):
def wrapper(*args):
print "enter func", func.__name__
return func(*args)
name = wrapper.__name__ + "_" + func.__name__
func_code = wrapper.func_code
new_code = CodeType(
func_code.co_argcount, func_code.co_nlocals, func_code.co_stacksize,
func_code.co_flags, func_code.co_code, func_code.co_consts,
func_code.co_names, func_code.co_varnames, func_code.co_filename,
name, func_code.co_firstlineno, func_code.co_lnotab,
func_code.co_freevars, func_code.co_cellvars)
wrapper = FunctionType(
new_code, wrapper.func_globals, name, wrapper.func_defaults,
wrapper.func_closure)
return wrapper
ここでは、関数の名前とコードオブジェクトの名前の両方がに設定されているためwrapper_originalfuncname、プロファイラーでラップされた関数とは別にカウントする必要があります。それらを元の関数の名前だけに簡単に設定して、実行時間が元の関数の名前にロールインされるようにすることができます。