The logic of the code is a rewrite of http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/408937, however partial is used here and default Exception class is added when no input is given. I have also made some modifications in the way handlers and exception classes are passed to the decorator. (it was earlier posted in comments for the same receipe)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | import functools
def ExpHandler(*pargs):
""" An exception handling idiom using decorators"""
def wrapper(f):
if pargs:
(handler,li) = pargs
t = [(ex, handler)
for ex in li ]
t.reverse()
else:
t = [(Exception,None)]
def newfunc(t,*args, **kwargs):
ex, handler = t[0]
try:
if len(t) == 1:
f(*args, **kwargs)
else:
newfunc(t[1:],*args,**kwargs)
except ex,e:
if handler:
handler(e)
else:
print e.__class__.__name__, ':', e
return functools.partial(newfunc,t)
return wrapper
def myhandler(e):
print 'Caught exception!', e
# Examples
# Specify exceptions in order, first one is handled first
# last one last.
@ExpHandler(myhandler,(ZeroDivisionError,))
@ExpHandler(None,(AttributeError, ValueError))
def f1():
1/0
@ExpHandler()
def f3(*pargs):
l = pargs
return l.index(10)
if __name__=="__main__":
f1()
f3()
|
I've done something similar. I built a very complete wrapper around Twisted deferreds that uses decorators in such a fashion to define handlers and such in the same structure as synchronous code, but mapping it to asynchronous handlers through Twisted deferreds.
http://cheeseshop.python.org/pypi/DeferArgs