I've written a program that needs to deal with a function that can throw multiple exceptions. For each exception I catch I have some code that will handle it specifically.
However, I also have some code I want to run no matter which exception was caught. My current solution is a handle_exception()
function which is called from each except
block.
try:
throw_multiple_exceptions()
except FirstException as excep:
handle_first_exception()
handle_exception()
except SecondException as excep:
handle_second_exception()
handle_exception()
Is there a better way to do this?
I would like the code to look like this:
try:
throw_multiple_exceptions()
except FirstException as excep:
handle_first_exception()
except SecondException as excep:
handle_second_exception()
except Exception as excep:
handle_exception()
how about PEP 0443? its awesome, and very scalable because all you have to do is code and register new handlers
from functools import singledispatch
@singledispatch
def handle_specific_exception(e): # got an exception we don't handle
pass
@handle_specific_exception.register(Exception1)
def _(e):
# handle exception 1
@handle_specific_exception.register(Exception2)
def _(e):
# handle exception 2
try:
throw_multiple_exceptions()
except Exception as e:
handle_specific_exception(e)
handle_exception()
You could do something like:
try:
throw_multiple_exceptions()
except FirstException, SecondException as excep:
if isinstance(excep, FirstException):
handle_first_exception()
else:
handle_second_exception()
handle_exception()
In case there are a lot of exceptions to handle, I suggest the way as follows:
from exceptions import ZeroDivisionError, AssertionError, Exception
def handle_first_exception():
print "First exception occurred"
def handle_second_exception():
print "Second exception occurred"
def handle_exception():
print "Exception occurred"
def throw_multiple_exceptions():
3/0 # |-> will output "First exception occurred"
assert 2 > 3 # |-> will output "Second exception occurred"
[1, 2, 3].index(0) # |-> will output "Exception occurred"
if __name__ == '__main__':
# more types of exceptions could be added to this dict
exceptions = { ZeroDivisionError: handle_first_exception, AssertionError: handle_second_exception }
try:
throw_multiple_exceptions()
except Exception as excep:
if type(excep) in exceptions.keys():
exceptions[type(excep)]()
else: handle_exception()
You may create a generic routine and pass additional callable object (function), depending on raised exception type.
def handle_first_exception():
pass
def handle_second_exception():
pass
handlers = {
FirstException: handle_first_exception
SecondException: handle_second_exception
}
def empty_handler():
pass
def handle_exception(f):
f() # call passed handler
# common code goes here
try:
throw_multiple_exceptions()
except Exception as e:
handle_exception(handlers.get(type(e), empty_handler))
Although I'll agree on comment discussion, a lot of exceptions with a lot of different except clauses seems a little bit like a code smell.