I was sent this snippet of Python:
try:
raise ExceptionGroup('group', [ValueError(123)])
except* ValueError:
print('Handling ValueError')
What does except* do?
except* is the new syntax for "Exception Groups" that will be added in Python 3.11.
See PEP 654 (specifically this section) for more details.
In brief, it captures one or more ValueError exceptions that may be part of a raised ExceptionGroup, without preventing additional except* clauses from handling other exceptions in the same group.
I know that I can do:
try:
# do something that may fail
except:
# do this if ANYTHING goes wrong
I can also do this:
try:
# do something that may fail
except IDontLikeYouException:
# say please
except 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 fail
except IDontLikeYouException:
# say please
except YouAreBeingMeanException:
# say please
Is there any way that I can do something like this (since the action to take in both exceptions is to say please):
try:
# do something that may fail
except IDontLikeYouException, YouAreBeingMeanException:
# say please
Now this really won't work, as it matches the syntax for:
try:
# do something that may fail
except 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?
From Python 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 using as.
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. The as keyword is used for the assignment. You can use any name for the error object, I prefer error 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 sys
try:
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 sys
try:
mainstuff()
except (KeyboardInterrupt, EOFError) as err:
print(err)
print(err.args)
sys.exit(0)
Note that in Python 3, the err object falls out of scope when the except 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 sys
try:
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.
The suppress context manager
The accepted answer is really 4 lines of code, minimum:
try:
do_something()
except (IDontLikeYouException, YouAreBeingMeanException) as e:
pass
The try, except, pass lines can be handled in a single line with the suppress context manager, available in Python 3.4:
from contextlib import suppress
with suppress(IDontLikeYouException, YouAreBeingMeanException):
do_something()
So when you want to pass on certain exceptions, use suppress.
From Python documentation -> 8.3 Handling Exceptions:
A try 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
except ValueError, e: was the syntax used for what is normally
written as except ValueError as e: in modern Python (described
below). The old syntax is still supported for backwards compatibility.
This means except RuntimeError, TypeError is not equivalent to
except (RuntimeError, TypeError): but to except RuntimeError as
TypeError: which is not what you want.
If you frequently use a large number of exceptions, you can pre-define a tuple, so you don't have to re-type them many times.
#This example code is a technique I use in a library that connects with websites to gather data
ConnectErrs = (URLError, SSLError, SocketTimeoutError, BadStatusLine, ConnectionResetError)
def connect(url, data):
#do 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 no exception occurred
NOTES:
If you, also, need to catch other exceptions than those in the
pre-defined tuple, you will need to define another except block.
If you just cannot tolerate a global variable, define it in main()
and pass it around where needed...
One of the way 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 is no exception then execute this block.
and another way is to create method which performs task executed by except block and call it through all of the except block that you write..
try:
You do your operations here;
......................
except Exception1:
functionname(parameterList)
except Exception2:
functionname(parameterList)
except Exception3:
functionname(parameterList)
else:
If there is no 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.
As of Python 3.11 you can take advantage of the except* clause that is used to handle multiple exceptions.
PEP-654 introduced a new standard exception type called ExceptionGroup that corresponds to a group of exceptions that are being propagated together. The ExceptionGroup can be handled using a new except* syntax. The * symbol indicates that multiple exceptions can be handled by each except* 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 see PEP-654.
I am trying to write a function that does error checking in the following way.
def check_var_type(var, var_name, type):
t = type(var)
if t is type or t is list:
return None
else:
return TypeError(
f"Invalid {var_name} type '{t.__module__}.{t.__name__}', "
f"'{float.__module__}.{float.__name__}' or "
f"'{list.__module__}.{list.__name__}' expected.")
my_var = 1
raise check(my_var, 'my_var', float)
My expectation of Python's raise command was that if I pass None to it, it would simply ignore it and raise no exception. The response, however, was:
TypeError: exceptions must derive from BaseException
I then had a look at Python's built-in exception types to see if something like Nonthing, NoError, etc. exists. No luck though.
I can, of course raise the exception in the check_var_type function, but I don't want to, since this would add an extra line to the stack trace.
So, my (perhaps silly) question is: How can I use raise to not raise an exception? :-)
Thanks
If you don't want to raise an exception, don't call raise (whose sole job IS to raise an exception).
Perhaps what you really want is to call raise from inside check_var_type when you actually do want to raise an exception, and just use return when you don't.
An alternative might be to leave check_var_type as is, but wrap the call to it in an if that one raises the exception returned when an exception is returned.
I have an issue trying to catch a Python exception:
File "/usr/lib/python2.7/dist-packages/numpy/lib/nanfunctions.py",
line 427, in nanargmax
raise ValueError("All-NaN slice encountered") ValueError: All-NaN slice encountered
The error appears with this code when effectively the slice contains All-NaN. However, I want to catch that situation and handle it.
with warnings.catch_warnings():
warnings.filterwarnings('error')
try:
action = np.nanargmax(self.Q[state])
except Warning as e:
print "error"
sys.exit(0)
I expect to print the word error, however, the try-except statement is ignored. Any help, please?
You should change except Warning as e to except ValueError as e.
This is because the ValueError class is not a subclass of the Warning class. Alternatively, you could catch any Exception with except Exception as e since all exceptions are a subclass of the Exception class, but best practice is to be as precise as possible with the exceptions that you catch.
This question already has answers here:
Python try...except comma vs 'as' in except
(5 answers)
Closed 9 years ago.
I am just being curious about the syntax of python exceptions as I can't seem to understand when you are suppossed to use the syntax below to catch an exception.
try:
"""
Code that can raise an exception...
"""
except Exception as e:
pass
and
try:
"""
Code that can raise an exception...
"""
except Exception, e:
pass
What is the difference?
Note: As Martijn points out, comma variable form is deprecated in Python 3.x. So, its always better to use as form.
As per http://docs.python.org/2/tutorial/errors.html#handling-exceptions
except Exception, e:
is equivalent to
except Exception as e:
Commas are still used when you are catching multiple exceptions at once, like this
except (NameError, ValueError) as e:
Remember, the parentheses around the exceptions are mandatory when catching multiple exceptions.
except Exception, e is deprecated in Python 3.
The proper form is:
try:
...
except Exception as e:
...
See: http://docs.python.org/3.0/whatsnew/2.6.html#pep-3110