Cameron Simpson <c...@zip.com.au> writes: > On 17Feb2009 15:12, J Kenneth King <ja...@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,
Ah, that's pretty interesting. I've found a couple other decorator-style recipes in the cookbooks online (http://code.activestate.com/recipes/408937/). I think you see my point: every single RPC call needs to be caught just in case because they are so volatile -- yet you're always looking for the exact same exception everywhere... too noisy to have inline try/except. I wonder if there are other use cases where Python developers have found the need to abstract away repetitive exception handling. I think this is the first I've seen the newer Python context managers being used (though it sneakily looks a lot like what Lisp calls, "unwind-protect"). Neat idea. -- http://mail.python.org/mailman/listinfo/python-list