Musings: Using decorators to reduce duplicate exception handling
Cameron Simpson
cs at zip.com.au
Wed Feb 18 16:33:50 EST 2009
On 17Feb2009 15:12, J Kenneth King <james at agentultra.com> wrote:
| I recently started a project called TracShell
| (http://code.google.com/p/tracshell) where I make heavy use of the
| xmlrpclib core module.
|
| When the number of RPC calls was small, wrapping each call in try/except
| was acceptable. [...]
| To combat the duplication, my clever idea was to use a function
| decorator to wrap any function that used xmlrpclib calls:
| def catch_errors(fn):
[...]
| Maybe I could rename the decorator to something meaningful, but besides
| that it works pretty well. Now any function I write in my class that
| uses RPC calls can be wrapped by this decorator and have the exception
| handling done in a uniform way for these particular exceptions.
My Python fu is still weak, but I had a similar issue last year and
wrote a context manager, used thus:
with NoExceptions(handler):
... do stuff that may break ...
The constructor takes a handleException argument (which may be None, but it
has to be explicit) to tune which exceptions are caught; default is
everything. This was for a daemon thread that did RPC calls, so it was
actually fairly important to never die; normally you'd want to catch only
specific exceptions.
Code:
class NoExceptions(object):
''' A context manager to catch _all_ exceptions and log them.
Arguably this should be a bare try...except but that's syntacticly
noisy and separates the catch from the top.
'''
def __init__(self, handleException):
''' Initialise the NoExceptions context manager.
The handleException is a callable which
expects (exc_type, exc_value, traceback)
and returns True or False for the __exit__
method of the manager.
If handleException is None, the __exit__ method
always returns True, suppressing any exception.
'''
self.__handler = handleException
def __enter__(self):
pass
def __exit__(self, exc_type, exc_value, traceback):
if self.__handler is not None:
return self.__handler(exc_type, exc_value, traceback)
if exc_type is not None:
print >>sys.stderr, "ignore %s" % (exc_type,)
return True
It doesn't actually solve your duplication issue and is a bit of a niche
application, but it's a lot shorter than an inline try/except and to my eye
reads a little better, and it keeps the exception handling up front at the
calling end where it is visible.
Cheers,
--
Cameron Simpson <cs at zip.com.au> DoD#743
http://www.cskk.ezoshosting.com/cs/
More information about the Python-list
mailing list