Raise and re-raise exceptions in Python

Choose appropriate Python exception types, preserve causes with raise from, and re-raise failures without relying on assertions for input validation.

Best practices
Python programming and application logging

Use raise with an exception instance, such as raise ValueError("Amount must be positive"). Choose a type that tells the caller what failed, and include enough context to make the message useful.

Validate a value

def validate_payment(amount, payment_type):
    if payment_type not in ("Visa", "Mastercard"):
        raise ValueError(f"Unsupported payment type: {payment_type}")
    if amount <= 0:
        raise ValueError("Amount must be positive")

try:
    validate_payment(100, "Discover")
except ValueError as error:
    print(f"Invalid payment: {error}")

This is a small validation example, not a complete payment implementation. Type, currency, precision, and authorization requirements belong in the actual payment code.

Select a meaningful type

Exception Typical meaning
ValueError An accepted type contains an invalid value
TypeError An unsupported argument type
KeyError A mapping key is missing
IndexError A sequence index is out of range
FileNotFoundError A requested file or directory does not exist
PermissionError An operation lacks the required access
RuntimeError A failure not covered by a more specific category
NotImplementedError A required operation has not been implemented

For an application-specific category, define a subclass of Exception and raise an instance of it.

Preserve the underlying cause

def read_count(text):
    try:
        return int(text)
    except ValueError as error:
        raise RuntimeError("Invalid count in configuration") from error

from error explicitly records the cause. The traceback can show both the low-level conversion error and your higher-level explanation. from None suppresses display of the implicit context; use it only when that presentation is intentional.

Re-raise the active exception

import logging

logger = logging.getLogger(__name__)

def load_count(text):
    try:
        return read_count(text)
    except Exception:
        logger.exception("Unable to load count")
        raise

A bare raise re-raises the exception currently being handled. With no active exception, it raises RuntimeError. Avoid logging the same failure repeatedly at every layer if an outer handler already records it.

FAQ

Can I raise the class itself? raise ValueError is allowed and constructs an exception without a message. This differs from a bare raise, which re-raises an active exception.

Why not use assert for validation? Assertions can be removed under python -O. Use explicit conditionals and raise for checks that must run in production.

Can I raise a string? No. Python requires an exception instance or a class derived from BaseException. Application exceptions should normally derive from Exception.

References

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting