I am trying to get correct function name while using 2 decorators.
1> profile - from memory_profiler import profile
2> custom timing decorator
def timing(f):
@wraps(f)
def wrapper(*args, **kwargs):
start = time()
result = f(*args, **kwargs)
end = time()
print 'Elapsed time: {} - {}'.format(wrapper.__name__, end - start)
return result
return wrapper
They are used in the following order as defined below
@timing
@profile
def my_function():
something.....
Problem is both functions work well individually but when used together I don't get correct name via the timing decorator. I always get wrapper
instead of the actual function name.
How do I get the actual function name instead of getting "wrapper" as the function name?
Dealt with the same problem today. In my case, I have a few decorators that extend other decorators by composition, and also take input arguments themselves. I needed to log some contextual information about the function being decorated, so I was naturally inclined to use the func.__name__
attribute, and I was getting the "wrapper"
string like you.
My solution might not be the most elegant one (by far) but it's legal and it worked 🤷
def log_context(logger):
def decorator(func):
def wrapper(*args, **kwargs):
logger.debug({
func.__name__: {
"args": args,
"kwargs": kwargs,
},
})
# Persist the name of the original function
# throughout the stack
wrapper.__name__ = func.__name__
return wrapper
return decorator
Then I can have something like this without a problem:
@log_context(logger)
@a_similar_decorator(logger)
def foo(x, y=None):
pass
foo(1, y=123)
This would output something like this:
{'foo': {'args': (1,), 'kwargs': {'y': 123}}}