Advanced Exception Architecture & Exception Chaining
Design resilient error handling with custom domain exceptions, explicit exception chaining (`raise NewError from original_err`), and modern Python 3.11+ Exception Groups (`except*`).
Interactive Sandbox Studio: 4 Tracks & 26 Competencies
Switch tracks and select any of the 26 core topics below to run production Python code, inspect CPython memory mechanics, and execute unit test assertion suites in real time.
Production Error Management Principles
- Preserve Traceback Context: Explicit exception chaining (`raise CustomError(...) from e`) populates `__cause__`, retaining low-level error stack traces without leaking implementation details to API callers.
- Domain-Specific Hierarchy: Inherit all application exceptions from a base `AppError(Exception)` to allow callers to catch high-level domain failures cleanly.
1. Designing Custom Exception Hierarchies
A well-designed exception hierarchy groups errors by domain, enabling callers to selectively catch coarse or fine-grained exceptions.
class ApplicationError(Exception):
"""Base exception for all application errors."""
pass
class DatabaseConnectionError(ApplicationError):
"""Raised when database host fails to respond."""
pass
class DataValidationError(ApplicationError):
"""Raised when inbound JSON payload violates domain constraints."""
pass
try:
raise DataValidationError("Field 'email' is required.")
except ApplicationError as err:
print(f"Caught Application Level Error: {type(err).__name__} -> {err}")
2. Explicit Exception Chaining (`raise ... from ...`)
Use `raise HighLevelError(...) from low_level_err` to transform technical errors into user-friendly domain errors while preserving original debugging context in `__cause__`.
import json
def parse_user_config(raw_json: str) -> dict:
try:
return json.loads(raw_json)
except json.JSONDecodeError as err:
# Explicitly chain JSONDecodeError into DataValidationError
raise DataValidationError("Failed to parse configuration JSON payload") from err
try:
parse_user_config("invalid_json_str{")
except DataValidationError as exc:
print("Handled Exception:", exc)
print("Underlying Root Cause:", repr(exc.__cause__))
3. Exception Groups & `except*` (Python 3.11+)
Python 3.11 introduced `ExceptionGroup` and `except*` to handle multiple concurrent failures simultaneously (e.g. parallel asyncio tasks or batch operations).
# Python 3.11+ Exception Group Example
eg = ExceptionGroup(
"Batch Task Failures",
[
ValueError("Invalid User ID"),
TypeError("Expected string, got int"),
KeyError("Missing 'auth_token' key")
]
)
try:
raise eg
except* ValueError as eg_val:
print("Handled ValueErrors:", eg_val.exceptions)
except* (TypeError, KeyError) as eg_type:
print("Handled Type & Key Errors:", eg_type.exceptions)