Skip to main content
Exception chaining is a mechanism in Python that links a newly raised exception to an originally caught exception, preserving the traceback history of both. This linkage is managed internally via the __context__, __cause__, and __suppress_context__ dunder attributes on the exception instances. Python supports two types of exception chaining: implicit and explicit, alongside a mechanism to intentionally suppress chaining.

Implicit Exception Chaining

Implicit chaining occurs automatically when a secondary exception is raised while an original exception is actively being handled (i.e., inside an except or finally block). When this happens, Python automatically assigns the original exception instance to the __context__ attribute of the newly raised exception instance. During traceback rendering, Python outputs a message indicating that an exception occurred during the handling of another exception.

Explicit Exception Chaining

Explicit chaining is triggered manually using the raise ... from ... syntax. This allows a developer to intentionally wrap an underlying exception with a new exception. When explicit chaining is used, Python assigns the original exception instance to the __cause__ attribute of the new exception instance. Additionally, it sets the __suppress_context__ boolean attribute on the new exception instance to True. During traceback rendering, Python outputs a message indicating that the original exception was the direct cause of the new exception.

Disabling Exception Chaining

To intentionally break the chain and prevent the original exception’s traceback from being displayed, Python provides the raise ... from None syntax. This syntax explicitly sets the __cause__ attribute of the new exception instance to None and sets its __suppress_context__ attribute to True. Because __suppress_context__ is true, the default traceback printer ignores the __context__ attribute, effectively hiding the original exception from the standard output.

Internal Attribute Resolution

When Python’s default exception handler prints a traceback, it evaluates the chaining attributes on the exception instance in the following order:
  1. It checks __cause__. If __cause__ is an exception object, it prints the explicit chain.
  2. If __cause__ is None, it checks __suppress_context__.
  3. If __suppress_context__ is False, it checks __context__. If __context__ is an exception object, it prints the implicit chain.
  4. If __suppress_context__ is True, it ignores __context__ entirely.
Tired of Poor Python Skills? Fix That With Deep Grasping!Learn More