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