Python | Raising an Exception to Another Exception

Let’s consider a situation where we want to raise an exception in response to catching a different exception but want to include information about both exceptions in the traceback.

To chain exceptions, use the raise from statement instead of a simple raise statement. This will give you information about both errors.

Code #1 :



filter_none

edit
close

play_arrow

link
brightness_4
code

def example():
    try:
        int('N/A')
    except ValueError as e:
        raise RuntimeError('A parsing error occurred') from e...
  
example()

chevron_right


Output :

Traceback (most recent call last):
  File "", line 3, in example
ValueError: invalid literal for int() with base 10: 'N/A'

This exception is the direct cause of the following exception –

Traceback (most recent call last):
  File "", line 1, in 
  File "", line 5, in example
RuntimeError: A parsing error occurred

Both exceptions are captured in the traceback. A normal except statement is used to catch such an exception. However, __cause__ attribute of the exception object can be looked to follow the exception chain as explained in the code given below.

Code #2 :

filter_none

edit
close

play_arrow

link
brightness_4
code

try:
    example()
except RuntimeError as e:
    print("It didn't work:", e)
    if e.__cause__:
        print('Cause:', e.__cause__)

chevron_right


An implicit form of chained exceptions occurs when another exception gets raised inside an except block.

Code #3 :

filter_none

edit
close

play_arrow

link
brightness_4
code

def example2():
    try:
        int('N/A')
    except ValueError as e:
        print("Couldn't parse:", err)
  
example2()

chevron_right


Traceback (most recent call last):
    File "", line 3, in example2
ValueError: invalid literal for int() with base 10: 'N / A'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
    File "", line 1, in 
    File "", line 5, in example2
NameError: global name 'err' is not defined

In the code below, the NameError exception is raised as the result of a programming error, not in direct response to the parsing error. For this case, the __cause__ attribute of an exception is not set. Instead, a __context__ attribute is set to the prior exception.

Code #4 : To suppress chaining, use raise from None

filter_none

edit
close

play_arrow

link
brightness_4
code

def example3():
    try:
        int('N / A')
    except ValueError:
        raise RuntimeError('A parsing error occurred') from None...
  
example3()

chevron_right


Output :

Traceback (most recent call last):
    File "", line 1, in 
    File "", line 5, in example3
RuntimeError: A parsing error occurred


My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.


Article Tags :

Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.