Musings: Using decorators to reduce duplicate exception handling

J Kenneth King james at agentultra.com
Wed Feb 18 10:15:51 EST 2009


"Gabriel Genellina" <gagsl-py2 at yahoo.com.ar> writes:

> En Tue, 17 Feb 2009 21:12:57 -0200, J Kenneth King
> <james at agentultra.com>  escribió:
>
>> 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. However, this obviously will duplicate code all over the
>> place. There are only ever two exceptions that the module itself will
>> throw: xmlrpclib.ProtocolError and xmlrpclib.Fault -- both very useful,
>> but not show stoppers.
>>
>> 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):
>>     """
>>     A decorator to catch typical xmlrpclib exceptions
>>     """
>>     def wrapped(*args, **kwargs):
>>         try:
>>             return fn(*args, **kwargs)
>>         except xmlrpclib.ProtocolError, e:
>>             print "There was a problem communicating with the server."
>>             print "URL: %s" % e.url
>>             print "Headers: %s" % e.headers
>>             print "Error code: %d" % e.errcode
>>             print "Error message: %s" % e.errmsg
>>             print "Please file a report with the TracShell developers."
>>             pass
>>         except xmlrpclib.Fault, e:
>>             print "A fault ocurred"
>>             print "Fault code: %d" % e.faultCode
>>             print "Fault string: %s" % e.faultString
>>             print "If you think this message is the result of an error,"
>>             print "please file a report with the TracShell developers."
>>             pass
>>     return wrapped
>
> I don't like the idea of "hiding" an exception. The caller code
> doesn't  know an exception occurred, and just continue doing its work,
> with bogus  results... is this what you want? Also, you don't include
> the stack trace  - and usually it contains very valuable
> information. When your users start  "filing a report with the
> TracShell developers" and you feel clueless, a  stack trace is
> important (you don't have to show it on screen - a log file  is even
> better).
>
> If all you want is to customize the error message, use sys.except_hook
>
> Looking into the code, those "pass" statement are useless; and error
> messages are usually written to stderr instead of stdout.

Thanks for the ideas.

I haven't actually used this pattern in any projects before, I was just
looking for a way to reduce the number of common try/except statements I
needed to have in my code; especially when they all looked exactly the
same and were catching every single xml-rpc call littered throughout my
class.

sys.except_hook looks more like what I was aiming for. I like Lisp's
"restarts," where I can define error condition handlers in one place
without having to litter my code with error handling statements.

Cheers.




More information about the Python-list mailing list