I'm going to guess that it's not the decorator itself that's cluttering up your profiling, but rather the wrapper function created by the decorator. And that's happening because all the wrapper functions have the same name. To address this, just have the decorator change the name of the wrapper function.
def decorator(func):
def wrapper(*args):
print "enter func", func.__name__
return func(*args)
wrapper.__name__ += "_" + func.__name__
return wrapper
You could also use functools.wraps()
, but then the name of the wrapper function will match the name of the function it's wrapping. I guess that would be OK for profiling.
Now, the function's code object also has a name. Python doesn't store references to functions on the stack, only to code objects, so if the profiler is getting the name of the wrapper function from a stack frame, it will get this name. Wrappers defined in the usual way share the code object (even though the function object is different) unless you explicitly rebuild the code object and the function object for each wrapper function. This is quite a bit more work and very CPython-specific (might even be version-specific). But here's how you might go about it:
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
Both the function's name and the code object's name are set here to wrapper_originalfuncname
and they should thus be counted separately from the wrapped function in the profiler. You could easily set them to just the original function's name so that their run time would be rolled in with the original function's instead.