Python quirks

Exception Chaining In Python

Today I read some Python code and I asked myself “mmm what? How does it work? What’s the meaning of raising an exception from another one? In this article I’ll answer on:

  1. What is an exception?
  2. What is an exception chaining?
  3. Why is it important to use it?
  4. How to chain exceptions in Python?

Let’s get started!

Introduction

Exception is a software error we, software developers, can create and handle (or not). It breaks the normal flow of the software and let us the option to run a special code when the software encounters one.

For example, if we divide a number by zero, we get an exception:

>>> 1/0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero

In this case, ZeroDivisionError is the exception. If we want to handle this exception we can wrap the dangerous code with try/except statements:

>>> try:
...     1/0
... except ZeroDivisionError:
...     print("Cannot divide by zero")
... 
Cannot divide by zero

What happens if an exception is thrown while handling another one?

>>> try:     
...     1/0
... except ZeroDivisionError as e:
...     print("error:", invalid_keyword_argument="oops")
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
TypeError: 'invalid_keyword_argument ' is an invalid keyword argument for print()

It’s nice to see that the interpreter knows that an exception occurred while handling another one.

Exception chaining

This is a programming technique which we can use by throwing an exception while catching one and link them together. In Python, there is an elegant way for doing so. We can achieve it by using raise ... from ...:

>>> class MyException(Exception): pass
... 
>>> try:
...     1/0
... except ZeroDivisionError as e:
...     print("Cannot divide by zero")
...     raise MyException("Failed to calculate the math formula") from e
... 
Cannot divide by zero
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: division by zero

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 5, in <module>
Exception: Failed to calculate the math formula

Earlier we saw the interpreter knows an exception was thrown while handling one, but this time, the message is different. Now, it tells us the exceptions are connected. If we don’t chain the exceptions together, the printed message implies that the exception-handling-code has issues regardless the original exception.

Importance

Exception chaining let us the option to add information to the original exception without discarding the original information. By doing so, each layer in our software design can:

  1. add its information to the exception- every layer can describe the layer’s status/problem without referring to some low/high level layers
  2. keep abstraction levels- when the levels are abstraced, we can maintain them easier than if they’re tangled/convulated.

References

https://docs.python.org/3/reference/simple_stmts.html#grammar-token-raise-stmt

https://en.wikipedia.org/wiki/Exception_chaining


If you have any questions feel free to comment or contact me directly.

Thank you for reading this. Please share and visit soon again,

Orian Zinger.

One thought on “Exception Chaining In Python

Leave a comment