Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Raising exceptions when an exception is already present in Python 3

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

Questions

  1. Where did my first exception go?
  2. Why is only the outermost exception catchable?
  3. How do I peel off the outermost exception and reraise the earlier exceptions?

Update0

This question specifically addresses Python 3, as its exception handling is quite different to Python 2.

like image 236
Matt Joiner Avatar asked Jun 08 '11 12:06

Matt Joiner


People also ask

Can you have two exceptions in Python?

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.

Is it possible to raise more than one exception at a time?

Strictly speaking you can't raise multiple exceptions but you could raise an object that contains multiple exceptions.

How do you raise a specific exception in Python?

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.

Does raising an exception stop the program Python?

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.


2 Answers

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 
like image 177
Frederico Mateus Martins Avatar answered Oct 04 '22 05:10

Frederico Mateus Martins


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

like image 24
Daniel Avatar answered Oct 04 '22 06:10

Daniel