Raising exceptions with raise

RoadmapsPython

Overview

The `raise` statement forces an exception to occur immediately. You use it to signal that an error condition has happened, passing the problem up to whoever called your function. def set_age(age): if age < 0: raise ValueError("Age cannot be negative") You instantiate an exception to halt execution. Inside an `except` block, calling a bare `raise` with no arguments re-raises the current exception with its original traceback preserved. try: set_age(-5) except ValueError: print("Logging error...") raise Unlike `raise err`, which can reset the traceback, a bare `raise` lets you log an error but still pass it up the chain untouched. def parse_payload(payload): try: user_id = payload["user_id"] except KeyError as e: raise ValueError("Invalid payload") # Trap: The original KeyError traceback is lost! When translating one exception into another, a simple `raise` obscures the root cause. You must use `raise NewError() from e` to link them, covered fully in exception-chaining.

Functions should rarely fail silently. If a function is asked to do something impossible, it should scream loudly by raising an exception. This forces the calling code to deal with the problem rather than continuing with a corrupted state or returning confusing `None` values. def withdraw(balance, amount): if amount > balance: raise ValueError("Insufficient funds") return balance - amount Choosing the right built-in type helps callers know what went wrong. For example, use `ValueError` for bad data, or `TypeError` for the wrong data type.

Where used: Validating function inputs and enforcing rules, Re-raising errors after logging them, Signaling business logic failures (e.g., `InsufficientFunds`)

Why learn this

Code walkthrough

def process_payment(amount):
    if amount <= 0:
        raise ValueError("Amount must be positive")
    print("Processing...")

try:
    process_payment(-50)
except ValueError as e:
    print(f"Caught: {e}")

Focus: The `raise ValueError(...)` immediately stops execution of `process_payment`, skips the `'Processing...'` print, and jumps straight into the caller's `except` block.

Common mistakes

Glossary

instantiate
The process of creating a specific object from a class blueprint. Example: `user = User()`.
corrupted state
When a program's internal data becomes invalid, inconsistent, or broken, often leading to unpredictable behavior. Example: `balance < 0`.

Recall questions

Understanding checks

What is wrong with this exception raising pattern?

The exception is raised as a class without an error message.

While technically valid Python, it's bad practice because `raise ValueError` provides no context. It should be instantiated with a helpful message: `raise ValueError('Cannot divide by zero')`.

What does a bare `raise` statement (with no arguments) do when used inside an `except` block?

It re-raises the exact exception that was just caught.

A bare `raise` maintains the original exception and its traceback, allowing you to log or inspect the error locally before letting it propagate up the call stack.

Practice tasks

Input validation

Modify the `set_age` function so that if `age` is less than `0`, it raises a `ValueError` with the message `'Age cannot be negative'`. Otherwise, it should return the `age`.

Challenge

Validate configuration

Write `check_config(cfg)` that takes a `dict`. If `'host'` is missing, raise a `KeyError`. If `'port'` is not an `int`, raise a `TypeError`. If `'port'` < `1024`, raise a `ValueError`.

Continue learning

Previous: try/except with specific exception types

Previous: Defining functions and return values

Next: Custom exception classes

Next: Exception chaining with raise from

Return to Python Roadmap