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.