Exception chaining enables users to see if an exception was triggered by another exception (see https://www.python.org/dev/peps/pep-3134/[PEP-3134]). Exceptions are chained using either of the following syntax: * ``++raise NewException() from chained_exception++`` * ``++new_exception.__cause__ = chained_exception++`` It is also possible to erase a chaining by setting ``++new_exception.__cause__ = None++`` or using ``++except ... from None++`` (see https://www.python.org/dev/peps/pep-0409/[PEP-409]). Chaining will fail and raise a ``++TypeError++`` if something else than ``++None++`` or a valid exception, i.e. an instance of ``++BaseException++`` or of a subclass, is provided. == Noncompliant Code Example ---- class A: pass try: raise ValueError("orig") except ValueError as e: new_exc = TypeError("new") new_exc.__cause__ = A() # Noncompliant raise new_exc try: raise ValueError("orig") except ValueError as e: raise TypeError("new") from "test" # Noncompliant ---- == Compliant Solution ---- try: raise ValueError("orig") except ValueError as e: new_exc = TypeError("new") new_exc.__cause__ = None # Ok raise new_exc try: raise ValueError("orig") except ValueError as e: new_exc = TypeError("new") new_exc.__cause__ = e # Ok raise new_exc try: raise ValueError("orig") except ValueError as e: raise TypeError("new") from None # Ok try: raise ValueError("orig") except ValueError as e: raise TypeError("new") from e # Ok ---- == See * PEP 3134 – https://www.python.org/dev/peps/pep-3134/[Exception Chaining and Embedded Tracebacks] * PEP 409 – https://www.python.org/dev/peps/pep-0409/[Suppressing exception context] * PEP 352 - https://www.python.org/dev/peps/pep-0352/#exception-hierarchy-changes[Required Superclass for Exceptions] * Python documentation - https://docs.python.org/3/library/exceptions.html[Built-in Exceptions]