21

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()

4 Answers 4

19

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()
Sign up to request clarification or add additional context in comments.

2 Comments

OP didn't say which version of Python, so it's probably worth mentioning that this feature was introduced in Python 3.4 and that there is a backport available for 2.6 through 3.3.
Beautiful. This provides a way to function overload in a dynamic language, something I've missed. Thanks!
9

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()

5 Comments

Won't it look bad if there are a lot of different exceptions?
@user4624535 if that's an issue, you probably have broader problems.
@user4624535 Having a function capable of throwing many different exceptions is likely a code smell. Perhaps the function is doing too many things?
@jonrsharpe But isn't using an if inside the except to classify the exception kind of steps over the idea behind multiple excepts?
@user4624535 ...what?
2

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()

Comments

1

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.

1 Comment

@rbp: To be fair, it's not a whole lot of lines longer than yours, and it's reasonably easy to understand. To me, this looks like what folks would use if they didn't have singledispatch available.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.