3956

I know that I can do:

try:    # do something that may failexcept:    # do this if ANYTHING goes wrong

I can also do this:

try:    # do something that may failexcept IDontLikeYouException:    # say pleaseexcept YouAreTooShortException:    # stand on a ladder

But if I want to do the same thing inside two different exceptions, the best I can think of right now is to do this:

try:    # do something that may failexcept IDontLikeYouException:    # say pleaseexcept YouAreBeingMeanException:    # say please

Is there a way that I can do something like this (since the action to take in both exceptions is tosay please):

try:    # do something that may failexcept IDontLikeYouException, YouAreBeingMeanException:    # say please

Now this really won't work, as it matches the syntax for:

try:    # do something that may failexcept Exception, e:    # say please

So, my effort to catch the two distinct exceptions doesn't exactly come through.

Is there a way to do this?

Peter Mortensen's user avatar
Peter Mortensen
31.4k22 gold badges110 silver badges134 bronze badges
askedJun 24, 2011 at 15:55
inspectorG4dget's user avatar
1
  • 49
    Note that in Python 3, the latter is no longer valid syntax.CommentedApr 17, 2019 at 14:01

6 Answers6

5269

FromPython Documentation:

An except clause may name multiple exceptions as a parenthesized tuple, for example

except (IDontLikeYouException, YouAreBeingMeanException) as e:    pass

Or, for Python 2 only:

except (IDontLikeYouException, YouAreBeingMeanException), e:    pass

Separating the exception from the variable with a comma will still work in Python 2.6 and 2.7, but is now deprecated and does not work in Python 3; now you should be usingas.

ArtOfCode's user avatar
ArtOfCode
5,7085 gold badges41 silver badges58 bronze badges
answeredJun 24, 2011 at 15:56
mechanical_meat's user avatar
Sign up to request clarification or add additional context in comments.

10 Comments

Is it possible to store desired exceptions in an iterable, and then catch the iterable? I'm trying to turn a list of warnings into errors usingwarnings.filterwarnings, and I don't want to have to specify the list of warnings twice.
I did try it... with alist, and it resulted in aTypeError. Looks like the errors must be in atuple for catching to work as expected.
It was unclear whether the "parenthesized tuple" was merely syntactical or that a bona fide tuple was required. "Parenthesized" is misleading because you may create a tuple without parentheses elsewhere and then use it in theexcept line. It is only necessarily parenthesized if created in theexcept line.
@JosephBani, what about generator expressions?
@JosephBani That's not true at all. In2 + (x * 2),(x * 2) is certainly not a tuple. Parentheses are a general grouping construct. The defining characteristic of a tuple is that it contains acomma -- seethe Python documentation: "Note that it is actually the comma which makes a tuple, not the parentheses."
|
552

How do I catch multiple exceptions in one line (except block)

Do this:

try:    may_raise_specific_errors():except (SpecificErrorOne, SpecificErrorTwo) as error:    handle(error) # might log or have some other default behavior...

The parentheses are required due to older syntax that used the commas to assign the error object to a name. Theas keyword is used for the assignment. You can use any name for the error object, I prefererror personally.

Best Practice

To do this in a manner currently and forward compatible with Python, you need to separate the Exceptions with commas and wrap them with parentheses to differentiate from earlier syntax that assigned the exception instance to a variable name by following the Exception type to be caught with a comma.

Here's an example of simple usage:

import systry:    mainstuff()except (KeyboardInterrupt, EOFError): # the parens are necessary    sys.exit(0)

I'm specifying only these exceptions to avoid hiding bugs, which if I encounter I expect the full stack trace from.

This is documented here:https://docs.python.org/tutorial/errors.html

You can assign the exception to a variable, (e is common, but you might prefer a more verbose variable if you have long exception handling or your IDE only highlights selections larger than that, as mine does.) The instance has an args attribute. Here is an example:

import systry:    mainstuff()except (KeyboardInterrupt, EOFError) as err:     print(err)    print(err.args)    sys.exit(0)

Note that in Python 3, theerr object falls out of scope when theexcept block is concluded.

Deprecated

You may see code that assigns the error with a comma. This usage, the only form available in Python 2.5 and earlier, is deprecated, and if you wish your code to be forward compatible in Python 3, you should update the syntax to use the new form:

import systry:    mainstuff()except (KeyboardInterrupt, EOFError), err: # don't do this in Python 2.6+    print err    print err.args    sys.exit(0)

If you see the comma name assignment in your codebase, and you're using Python 2.5 or higher, switch to the new way of doing it so your code remains compatible when you upgrade.

Thesuppress context manager

The accepted answer is really 4 lines of code, minimum:

try:    do_something()except (IDontLikeYouException, YouAreBeingMeanException) as e:    pass

Thetry,except,pass lines can be handled in a single line with thesuppress context manager, available in Python 3.4:

from contextlib import suppresswith suppress(IDontLikeYouException, YouAreBeingMeanException):     do_something()

So when you want topass on certain exceptions, usesuppress.

answeredJun 21, 2014 at 4:20
Aaron Hall's user avatar

4 Comments

Good addition ofsuppress, a lot more readable than just doingpass onexcept
Can you log the exception and then pass it outside the with context manager?
@Mache: I do not find the suppress() syntax more readable personally. But maybe it’s matter of habit. Moreover, isn’t the import of this function from another library, for such a simple use, a useless overhead?
@Stéphane runtime overhead of importing is only once (during startup), and python starts are slow anyways. Maintenance overhead is nil, because contextlib is in the standard library and therefore future-proof and everywhere-available.
76

FromPython documentation -> 8.3 Handling Exceptions:

Atry statement may have more than one except clause, to specify handlers for different exceptions. At most one handler will be executed. Handlers only handle exceptions that occur in the corresponding try clause, not in other handlers of the same try statement. An except clause may name multiple exceptions as a parenthesized tuple, for example:

except (RuntimeError, TypeError, NameError):    pass

Note that the parentheses around this tuple are required, because exceptValueError, e: was the syntax used for what is normally written asexcept ValueError as e: in modern Python (described below). The old syntax is still supported for backwards compatibility. This meansexcept RuntimeError, TypeError is not equivalent toexcept (RuntimeError, TypeError): but toexcept RuntimeError asTypeError: which is not what you want.

answeredOct 30, 2014 at 10:01
fedorqui's user avatar

Comments

63

If you frequently use a large number of exceptions, you can predefine a tuple, so you don't have to retype them many times.

# This example code is a technique I use in a library# that connects with websites to gather dataConnectErrs = (URLError, SSLError, SocketTimeoutError, BadStatusLine, ConnectionResetError)def connect(url, data):    # Do a connection and return some data    return(received_data)def some_function(var_a, var_b, ...):    try: o = connect(url, data)    except ConnectErrs as e:        # Do the recovery stuff    blah # Do normal stuff you would do if an exception does not occur

Notes:

  1. If you, also, need to catch other exceptions than those in thepre-defined tuple, you will need to define another except block.

  2. If you just cannot tolerate a global variable, define it in main()and pass it around where needed...

Peter Mortensen's user avatar
Peter Mortensen
31.4k22 gold badges110 silver badges134 bronze badges
answeredSep 18, 2017 at 1:36
whitebeard's user avatar

Comments

35

One of the ways to do this is...

try:   You do your operations here;   ......................except(Exception1[, Exception2[,...ExceptionN]]]):   If there is any exception from the given exception list,   then execute this block.   ......................else:   If there isn't any exception, then execute this block.

And another way is to create a method which performs a task executed by anexcept block and call it through all of theexcept blocks that you write...

try:   You do your operations here;   ......................except Exception1:    functionname(parameterList)except Exception2:    functionname(parameterList)except Exception3:    functionname(parameterList)else:   If there isn't any exception, then execute this block.def functionname( parameters ):   // Your task..   return [expression]

I know that second one is not the best way to do this, but I'm just showing number of ways to do this thing.

Peter Mortensen's user avatar
Peter Mortensen
31.4k22 gold badges110 silver badges134 bronze badges
answeredAug 17, 2017 at 11:56
M.Usman's user avatar

4 Comments

I'm using the second one because I have two different exceptions that each need to be processed differently. Is there something wrong with doing it that way?
@majikman The second method with multiple clauses each calling the same function is not the best when you're trying to not repeat yourself and doing the same thing for two exceptions. (See the other answers for the right way to do that). However, having multipleexcept clauses is normal when you want to handle the exceptions differently.
The second way is actually awesome
I dislike such function calls in except-clauses. Except-clauses often contain log-statements, and this extra-function obscures the relationship between the logged message (containing a file&line-number) and the location of the error in code. Also, good error-handling usually needs a lot of context from the surrounding function, so your parameter-list will either get long or lose context.
30

As of Python 3.11 you can take advantage of theexcept* clause that is used to handle multiple exceptions.

PEP-654 introduced a new standard exception type calledExceptionGroup that corresponds to a group of exceptions that are being propagated together. TheExceptionGroup can be handled using a newexcept* syntax. The* symbol indicates that multiple exceptions can be handled by eachexcept* clause.


For example, you can handle multiple exceptions

try:    raise ExceptionGroup('Example ExceptionGroup', (        TypeError('Example TypeError'),        ValueError('Example ValueError'),        KeyError('Example KeyError'),        AttributeError('Example AttributeError')    ))except* TypeError:    ...except* ValueError as e:    ...except* (KeyError, AttributeError) as e:    ...

For more details seeException Groups andexcept-* in the official python docs.

The historic PEP isPEP-654.

julaine's user avatar
julaine
2,3131 gold badge20 silver badges38 bronze badges
answeredApr 2, 2022 at 0:09
Giorgos Myrianthous's user avatar

2 Comments

How does this help "catch multiple exceptions in one line" as the question requires?
Exception groups andexcept* are about throwing and catching multiple exceptions that are being propagated at the same time. This question and accepted answer is about a single exception being thrown, you just don't know which one and want to handle several possibilities with the same code-snippet. The Question and accepted answers don't clearly state that difference because at their time of writing, there was always only a single exception being propagated.
Protected question. To answer this question, you need to have at least 10 reputation on this site (not counting theassociation bonus). The reputation requirement helps protect this question from spam and non-answer activity.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.