
Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
Standard Way of Using Exception Chains in Python 3
In Python 3, exception chaining allows one exception to be raised while preserving the context of the original exception. This provides a complete track, which makes it easy to understand how an error occurred during debugging.
Python supports exception chaining explicitly using the raise ... from ... statement, or implicitly when a new exception is raised while handling another.
Using raise ... from ... Statement
This is the standard way to explicitly chain exceptions. The second exception is raised with a reference to the original exception using the from keyword, which helps to track the cause of the error.
Example: Chaining ValueError from ZeroDivisionError
In the following example, we are dividing by zero and then raising a new ValueError while explicitly chaining it from the original exception -
try: x = 1 / 0 except ZeroDivisionError as e: raise ValueError("Secondary error occurred") from e
We get the following output -
Traceback (most recent call last): ... ZeroDivisionError: division by zero The above exception was the direct cause of the following exception: Traceback (most recent call last): ... ValueError: Secondary error occurred
Implicit Exception Chaining
When a new exception is raised inside an except block without using from, Python automatically links the exceptions using the context. This is known as implicit exception chaining.
Example: Implicit chaining in nested exception
In the following example, we are raising a TypeError inside an except block without using from, which leads to implicit chaining -
try: int("abc") except ValueError: raise TypeError("Follow-up error occurred")
We get the following output -
Traceback (most recent call last): ... ValueError: invalid literal for int() with base 10: 'abc' During handling of the above exception, another exception occurred: Traceback (most recent call last): ... TypeError: Follow-up error occurred
Suppressing Exception Context
In some cases, you may not want to show the original exception. You can suppress the exception context by setting from None when raising the new exception.
Example
In the following example, we are raising a new exception while explicitly removing the traceback of the original exception -
try: int("abc") except ValueError: raise RuntimeError("Suppressed original exception") from None
We get the following output -
Traceback (most recent call last): ... RuntimeError: Suppressed original exception
Best Practice for Exception Chaining
Use raise ... from ... when you want to keep the traceback for debugging and provide better context. Avoid implicit chaining when clarity is needed, and suppress it only when the original exception is irrelevant.
Example: Using custom exceptions with chaining
In the following example, we are using a custom exception class and chaining it from a built-in exception for better debugging -
class MyCustomError(Exception): pass try: result = int("xyz") except ValueError as e: raise MyCustomError("Custom conversion failure") from e
We get the following output -
Traceback (most recent call last): ... ValueError: invalid literal for int() with base 10: 'xyz' The above exception was the direct cause of the following exception: Traceback (most recent call last): ... MyCustomError: Custom conversion failure