0% complete

Functions, modules, and error handling · Lesson 2 of 3

Exceptions and defensive error handling

Raise and catch specific exceptions at the layer that can respond meaningfully.

Lesson

1. Concept and mental model

Exceptions communicate that an operation could not complete as requested. Python raises exceptions for conditions such as invalid numeric conversion, a missing dictionary key, or a failed file operation. Catch the narrow exception that you can handle, such as ValueError when parsing user input. A broad except Exception can accidentally hide programming bugs and should not be used as a routine substitute for understanding failure modes.

2. How it works

Use try for the operation that may fail, except for the recovery you can actually provide, and else for work that should happen only when the operation succeeds. A finally block is useful for cleanup that must happen regardless of success; context managers such as with open(...) usually manage resources more clearly. When the current layer cannot recover, let the exception propagate or raise a domain-specific exception with useful context using raise ... from error.

3. Use it safely and effectively

Validate at system boundaries and report actionable messages without exposing secrets, raw credentials, or unnecessary internal details. Do not use exceptions for ordinary branching when a simple condition expresses the rule. Test both success and failure paths, including the exception type and expected user-facing behavior. A reliable program defines how it handles bad input, unavailable files, timeouts, and partial operations.

4. Syntax reference

try:
    quantity = int('12')
except ValueError as error:
    print(f'Invalid quantity: {error}')
else:
    print(quantity * 2)

5. Guided walkthrough

Put only the operation that may fail inside the try block, catch an exception your code can recover from, and give the caller a specific message or result. If you cannot safely recover, preserve the failure so the layer with enough context can respond.

6. Common mistakes to avoid

  • Catching every exception and continuing with a fake success value.
  • Putting unrelated operations inside one large try block, which makes it unclear which operation failed.

Visual guide

Handle an operation safely

  1. Step 01 Attempt

    Run the operation that may fail.

  2. Step 02 Recover

    Catch a specific recoverable exception.

  3. Step 03 Report

    Return a clear result or propagate failure.

Code examples

Worked example
PYTHON
try:
    quantity = int('12')
except ValueError as error:
    print(f'Invalid quantity: {error}')
else:
    print(quantity * 2)
Expected output
24
Parse user data with a useful fallback
PYTHON
raw_value = '12x'
try:
    value = int(raw_value)
except ValueError:
    print('Enter a whole number.')
Expected output
Enter a whole number.
Raise a clear domain error
PYTHON
def withdraw(balance: float, amount: float) -> float:
    if amount <= 0:
        raise ValueError('Amount must be positive')
    if amount > balance:
        raise ValueError('Insufficient funds')
    return balance - amount
Expected output
Returns the remaining balance or raises ValueError.

Key points

  • Raise and catch specific exceptions at the layer that can respond meaningfully.
  • Prefer explicit, testable behavior over hidden side effects.
  • Validate assumptions at system boundaries and handle failure deliberately.

Check your understanding

Practice

Which exception is appropriate for invalid integer text?

Your learning progress

Finish this lesson