Python Decorators and SimpleXMLRPCServer

While working on an XML-RPC server for App Engine, I came across an interesting problem. I wanted to add a way to get performance measurements for my calls, so I wrote a simple decorator that returns a tuple of the result and the time it took to complete.
from SimpleXMLRPCServer import CGIXMLRPCRequestHandler
import time
import functools

def timed(func):
@functools.wraps(func)
def decorator(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
return result, time.time() - start
return decorator

@timed
def mypow(*args):
return pow(*args)

if __name__ == '__main__':
handler = CGIXMLRPCRequestHandler()
handler.register_function(mypow)
handler.handle_request()
The key to making this work is functools.wraps(). Without it, the function returned by the decorator no longer has the same name as the original function. So, when I register the function, the call fails. You can fix this by hand (or pre 2.5) by changing your decorator like so:
def timed(func):
def decorator(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
return result, time.time() - start
decorator.__name__ = func.__name__
return decorator
But functools.wraps() sets some additional attributes as well.

No comments:

Post a Comment