What happens to my first exception (A
) when the second (B
) is raised in the following code?
class A(Exception): pass class B(Exception): pass try: try: raise A('first') finally: raise B('second') except X as c: print(c)
If run with X = A
I get:
Traceback (most recent call last): File "raising_more_exceptions.py", line 6, in raise A('first') __main__.A: first During handling of the above exception, another exception occurred: Traceback (most recent call last): File "raising_more_exceptions.py", line 8, in raise B('second') __main__.B: second
But if X = B
I get:
second
This question specifically addresses Python 3, as its exception handling is quite different to Python 2.
By handling multiple exceptions, a program can respond to different exceptions without terminating it. In Python, try-except blocks can be used to catch and respond to one or multiple exceptions. In cases where a process raises more than one possible exception, they can all be handled using a single except clause.
Strictly speaking you can't raise multiple exceptions but you could raise an object that contains multiple exceptions.
As a Python developer you can choose to throw an exception if a condition occurs. To throw (or raise) an exception, use the raise keyword.
except block is completed and the program will proceed. However, if an exception is raised in the try clause, Python will stop executing any more code in that clause, and pass the exception to the except clause to see if this particular error is handled there.
Answering to question 3, you can use:
raise B('second') from None
Which will remove the exception A
traceback.
Traceback (most recent call last): File "raising_more_exceptions.py", line 8, in raise B('second') __main__.B: second
The 'causing' exception is available as c.__context__ in your last exception handler. Python is using this information to render a more useful traceback. Under Python 2.x the original exception would have been lost, this is for Python 3 only.
Typically you would use this to throw a consistent exception while still keeping the original exception accessible (although it's pretty cool that it happens automatically from an exception handler, I didn't know that!):
try: do_something_involving_http() except (URLError, socket.timeout) as ex: raise MyError('Network error') from ex
More info (and some other pretty useful things you can do) here: http://docs.python.org/3.3/library/exceptions.html
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