Error Handling Patterns
Exception hierarchies, retry patterns, and error recovery.
Overview
Master error handling patterns.
Exception Hierarchy
class AppError(Exception):
"""Base application error"""
pass
class ValidationError(AppError):
"""Validation failed"""
def __init__(self, field, message):
self.field = field
self.message = message
super().__init__(f"{field}: {message}")
class NotFoundError(AppError):
"""Resource not found"""
def __init__(self, resource, identifier):
self.resource = resource
self.identifier = identifier
super().__init__(f"{resource} {identifier} not found")
class DatabaseError(AppError):
"""Database operation failed"""
pass
Retry Pattern
import time
from functools import wraps
def retry(max_attempts=3, delay=1, backoff=2):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
attempts = 0
current_delay = delay
while attempts < max_attempts:
try:
return func(*args, **kwargs)
except Exception as e:
attempts += 1
if attempts == max_attempts:
raise
time.sleep(current_delay)
current_delay *= backoff
return wrapper
return decorator
@retry(max_attempts=3, delay=1)
def unreliable_api_call():
import random
if random.random() < 0.7:
raise ConnectionError("API unavailable")
return {"status": "ok"}
Error Recovery
from contextlib import contextmanager
@contextmanager
def error_recovery(fallback_value=None):
try:
yield
except Exception as e:
print(f"Error: {e}, using fallback")
return fallback_value
# Usage
with error_recovery(fallback_value=[]):
result = risky_operation()
Practice
Implement a circuit breaker pattern for API calls.