When handling exceptions in python, I find myself repeating code quite often. The basic pattern is something of the form:
try:
action_here()
except CommonException1:
Action_always_taken_for_CommonException1()
except CommonException2:
Action_always_taken_for_CommonException2()
except Exception:
Default_action_always_taken()
What I would like to do is to some how abstract this repetitive code out to a function or class. I know one way to do it is to call an exception handling function with the exception object, such as:
try:
action_here()
except Exception as e:
handle_exception(e)
Then in this function determine the exception based on class.
def handle_exception(e):
if type(e) == type(CommonException1()):
Action_always_taken_for_CommonException1()
elif type(e) == type(CommonException2()):
Action_always_taken_for_CommonException2())
else:
Default_action_always_taken()
This, however, feels clunky and inelegant. So my question is, what are some other alternatives to handling repetitive exception handling?
This situation is one of the main use cases for context managers and the with statement:
from __future__ import with_statement # Needed in 2.5, but not in 2.6 or later
from contextlib import contextmanager
@contextmanager
def handle_exceptions():
try:
yield # Body of the with statement effectively runs here
except CommonException1:
Action_always_taken_for_CommonException1()
except CommonException2:
Action_always_taken_for_CommonException2()
except Exception:
Default_action_always_taken()
# Used as follows
with handle_exceptions():
action_here()
If you dislike the repeated if
/ elseif
blocks, you could put your handles in a dict, keyed by type:
handlers = { type(CommonException1()) : Action_always_taken_forCommonException1,
type(CommonException2()) : Action_always_taken_forCommonException2 }
def handle_exception(te):
if te in handlers:
handlers[te]()
else:
Default_action()
Which you could then run with:
try:
action_here()
except Exception as e:
handle_exception(type(e))
In addition: If you find yourself writing these try blocks frequently, then you could write your own context manager (see here). At the action_here()
side, your code would then look like this:
with my_error_handling_context():
action_here1()
action_here2()
In this case, the handle_exception
code would essentially be your context manager's __exit__
method (which will always get passed any exceptions raised during the with block).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With