Bird
Raised Fist0
Pythonprogramming~10 mins

Exception chaining in Python - Step-by-Step Execution

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Concept Flow - Exception chaining
Start try block
Exception occurs
Catch exception as e
Raise new exception from e
Python links exceptions
Exception chain shown in traceback
When an error happens inside a try block, you catch it and raise a new error using 'from' to link them. Python shows both errors together.
Execution Sample
Python
try:
    x = 1 / 0
except ZeroDivisionError as e:
    raise ValueError("Bad value") from e
This code tries to divide by zero, catches that error, then raises a new error linked to the first one.
Execution Table
StepActionException RaisedException CaughtException ChainingOutput/Traceback
1Execute 'x = 1 / 0'ZeroDivisionErrorNoNoNo output yet
2Catch ZeroDivisionError as eZeroDivisionErrorZeroDivisionError caughtNoNo output yet
3Raise ValueError from eValueErrorValueError raisedValueError linked to ZeroDivisionErrorTraceback shows both exceptions chained
4Program stops with chained exceptionsValueErrorNo further catchChain displayedTraceback printed with cause
💡 Program stops after raising ValueError chained from ZeroDivisionError
Variable Tracker
VariableStartAfter Step 1After Step 2After Step 3Final
xundefinedError raised, no value assignedNo changeNo changeNo value due to error
eundefinedundefinedZeroDivisionError instanceNo changeZeroDivisionError instance
Key Moments - 3 Insights
Why do we use 'raise ... from e' instead of just 'raise'?
Using 'raise ... from e' links the new exception to the original one, showing both errors in the traceback (see execution_table step 3). Just 'raise' re-raises the same exception without chaining.
What happens if we don't catch the original exception before raising a new one?
If you raise a new exception without catching the original, Python won't link them. The chain only forms when you use 'from' with a caught exception (see execution_table step 2 and 3).
Does the original exception stop the program immediately?
No, the original exception is caught first (step 2), then a new exception is raised (step 3). The program stops only after the new exception is not caught.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, what exception is caught at step 2?
AZeroDivisionError
BTypeError
CValueError
DNo exception caught
💡 Hint
Check the 'Exception Caught' column at step 2 in the execution_table.
At which step does Python link the new exception to the original one?
AStep 2
BStep 3
CStep 1
DStep 4
💡 Hint
Look at the 'Exception Chaining' column to find when chaining happens.
If we remove 'from e' in the raise statement, what changes in the output?
AThe traceback shows both exceptions chained
BThe program runs without errors
CThe traceback shows only the new exception without the original cause
DThe original exception is re-raised instead
💡 Hint
Refer to the explanation in key_moments about 'raise ... from e' usage.
Concept Snapshot
Exception chaining in Python:
Use 'raise NewError() from original_error' inside except block.
This links the new error to the original one.
Traceback shows both exceptions for easier debugging.
Without 'from', only the new error appears.
Helps track error causes clearly.
Full Transcript
This example shows how Python handles exception chaining. When an error happens inside a try block, it is caught in the except block as 'e'. Then a new exception is raised using 'raise ... from e' which links the new exception to the original one. The execution table traces each step: first the ZeroDivisionError occurs, then it is caught, then a ValueError is raised from it. The variable tracker shows that 'x' never gets a value because of the error, and 'e' holds the original exception. Key moments clarify why 'from e' is important to keep the chain visible in the traceback. The visual quiz tests understanding of which exceptions are caught, when chaining happens, and what happens if 'from e' is removed. The concept snapshot summarizes the syntax and purpose of exception chaining in Python.

Practice

(1/5)
1.

What does raise NewError() from OriginalError() do in Python?

easy
A. It links the new error to the original error, showing both in the traceback.
B. It ignores the original error and raises only the new error.
C. It catches the original error and prevents any error from being raised.
D. It raises both errors separately without linking them.

Solution

  1. Step 1: Understand exception chaining syntax

    The syntax raise NewError() from OriginalError() explicitly links the new error to the original one.
  2. Step 2: Effect on traceback

    This chaining shows both errors in the error message, helping to trace the root cause.
  3. Final Answer:

    It links the new error to the original error, showing both in the traceback. -> Option A
  4. Quick Check:

    Exception chaining = linked errors [OK]
Hint: Remember 'from' links errors to show full traceback [OK]
Common Mistakes:
  • Thinking it hides the original error
  • Believing it raises errors separately
  • Confusing it with catching exceptions
2.

Which of the following is the correct syntax to chain exceptions in Python?

try:
    1 / 0
except ZeroDivisionError as e:
    ???
easy
A. raise ValueError() and e
B. raise ValueError() from e
C. raise ValueError() with e
D. raise ValueError(e)

Solution

  1. Step 1: Recall correct chaining syntax

    To chain exceptions, use raise NewError() from original_error.
  2. Step 2: Match syntax to options

    raise ValueError() from e uses raise ValueError() from e, which is correct syntax.
  3. Final Answer:

    raise ValueError() from e -> Option B
  4. Quick Check:

    Correct chaining syntax uses 'from' keyword [OK]
Hint: Use 'raise ... from ...' to chain exceptions [OK]
Common Mistakes:
  • Using parentheses incorrectly
  • Using 'with' or 'and' instead of 'from'
  • Passing original error as argument without 'from'
3.

What will be the output of this code?

def f():
    try:
        1 / 0
    except ZeroDivisionError as e:
        raise ValueError("Invalid value") from e

try:
    f()
except Exception as ex:
    print(type(ex).__name__)
    print(ex.__cause__)
medium
A. ZeroDivisionError\nNone
B. ValueError\nNone
C. ValueError\ndivision by zero
D. ZeroDivisionError\nValueError('Invalid value')

Solution

  1. Step 1: Trace function f()

    Inside f(), dividing by zero raises ZeroDivisionError, caught as e.
  2. Step 2: Raise ValueError chained from ZeroDivisionError

    The code raises ValueError with message "Invalid value" from e, linking the original ZeroDivisionError.
  3. Step 3: Catch exception and print details

    The outer try-except catches the ValueError, prints its type, then prints its __cause__, which is the original ZeroDivisionError.
  4. Final Answer:

    ValueError division by zero -> Option C
  5. Quick Check:

    Chained error shows new error and original cause [OK]
Hint: Chained exceptions show new error and original cause [OK]
Common Mistakes:
  • Expecting __cause__ to be None
  • Confusing error types printed
  • Missing that ValueError is raised
4.

Identify the error in this code snippet:

try:
    int('abc')
except ValueError as e:
    raise TypeError('Wrong type') from
medium
A. ValueError because int conversion failed
B. TypeError because 'from' cannot be used here
C. No error, code runs fine
D. SyntaxError due to incomplete 'from' statement

Solution

  1. Step 1: Check the 'raise' statement syntax

    The statement ends with 'from' but does not specify the original exception after it.
  2. Step 2: Understand Python syntax rules

    The 'from' keyword must be followed by an exception instance or variable; missing this causes SyntaxError.
  3. Final Answer:

    SyntaxError due to incomplete 'from' statement -> Option D
  4. Quick Check:

    Incomplete 'from' causes SyntaxError [OK]
Hint: Always provide an exception after 'from' [OK]
Common Mistakes:
  • Leaving 'from' without exception
  • Thinking 'from' is optional
  • Confusing runtime error with syntax error
5.

You want to write a function that reads a number from a string and raises a custom MyError if conversion fails, but also keep the original error for debugging. Which code correctly implements exception chaining?

class MyError(Exception):
    pass

def read_number(s):
    try:
        return int(s)
    except ValueError as e:
        ???
hard
A. raise MyError('Invalid number') from e
B. raise MyError('Invalid number')
C. raise ValueError('Invalid number') from e
D. raise MyError('Invalid number', e)

Solution

  1. Step 1: Understand the goal

    The function should raise MyError but keep original ValueError linked for debugging.
  2. Step 2: Use exception chaining syntax

    Using raise MyError(...) from e correctly chains the new error to the original.
  3. Step 3: Evaluate options

    raise MyError('Invalid number') from e uses correct chaining syntax; others either lose original error or misuse arguments.
  4. Final Answer:

    raise MyError('Invalid number') from e -> Option A
  5. Quick Check:

    Use 'raise ... from e' to chain custom errors [OK]
Hint: Chain custom errors with 'raise ... from e' [OK]
Common Mistakes:
  • Not chaining original error
  • Passing original error as argument incorrectly
  • Raising wrong exception type