Bird
Raised Fist0
Pythonprogramming~20 mins

Exception chaining in Python - Practice Problems & Coding Challenges

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
Challenge - 5 Problems
🎖️
Exception Chaining Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
Predict Output
intermediate
2:00remaining
Output of chained exceptions with raise from
What is the output of this Python code when executed?
Python
def func():
    try:
        x = 1 / 0
    except ZeroDivisionError as e:
        raise ValueError("Invalid value") from e

try:
    func()
except Exception as ex:
    print(type(ex).__name__)
    print(ex)
    print(type(ex.__cause__).__name__)
    print(ex.__cause__)
A
ValueError
Invalid value
ZeroDivisionError
division by zero
B
ZeroDivisionError
division by zero
ValueError
Invalid value
C
ValueError
Invalid value
None
None
D
ZeroDivisionError
Invalid value
ValueError
division by zero
Attempts:
2 left
💡 Hint
Remember that 'raise ... from ...' sets the __cause__ attribute of the new exception.
Predict Output
intermediate
2:00remaining
Effect of exception chaining without 'from'
What will be printed by this code?
Python
try:
    try:
        int('abc')
    except ValueError:
        raise RuntimeError('Conversion failed')
except Exception as e:
    print(type(e).__name__)
    print(e)
    print(e.__cause__)
A
RuntimeError
Conversion failed
ValueError('invalid literal for int() with base 10: \'abc\'')
B
ValueError
invalid literal for int() with base 10: 'abc'
None
C
RuntimeError
Conversion failed
None
D
RuntimeError
Conversion failed
RuntimeError
Attempts:
2 left
💡 Hint
Without 'from', the __cause__ attribute is not set automatically.
🔧 Debug
advanced
2:00remaining
Identify the error in exception chaining syntax
Which option contains a syntax error related to exception chaining?
A
try:
    1/0
except ZeroDivisionError as e:
    raise ValueError('Error') from e
B
try:
    1/0
except ZeroDivisionError as e:
    raise ValueError('Error') with e
C
e morf )'rorrE'(rorrEeulaV esiar    
:e sa rorrEnoisiviDoreZ tpecxe
0/1    
:yrt
D
try:
    1/0
except ZeroDivisionError as e:
    raise ValueError('Error')
Attempts:
2 left
💡 Hint
Check the keyword used to chain exceptions.
Predict Output
advanced
2:00remaining
Output of nested exception chaining with __context__
What will this code print?
Python
def f():
    try:
        int('a')
    except ValueError:
        try:
            1/0
        except ZeroDivisionError:
            raise RuntimeError('Runtime problem')

try:
    f()
except Exception as e:
    print(type(e).__name__)
    print(e)
    print(type(e.__context__).__name__)
    print(e.__context__)
A
ZeroDivisionError
division by zero
ValueError
invalid literal for int() with base 10: 'a'
B
RuntimeError
Runtime problem
ValueError
invalid literal for int() with base 10: 'a'
C
RuntimeError
Runtime problem
None
None
D
RuntimeError
Runtime problem
ZeroDivisionError
division by zero
Attempts:
2 left
💡 Hint
When an exception is raised during handling another, __context__ stores the original exception.
🧠 Conceptual
expert
2:00remaining
Understanding implicit vs explicit exception chaining
Which statement best describes the difference between implicit and explicit exception chaining in Python?
AExplicit chaining uses 'raise ... from ...' to set __cause__, while implicit chaining sets __context__ automatically when an exception occurs during handling another.
BImplicit chaining uses 'raise ... from ...' to set __cause__, while explicit chaining sets __context__ automatically.
CExplicit chaining sets __context__ to None, implicit chaining sets __cause__ to None.
DImplicit chaining requires manual assignment of __cause__, explicit chaining happens automatically.
Attempts:
2 left
💡 Hint
Think about how Python links exceptions automatically versus when you use 'from'.

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