Exception Handling Patterns
Common Exception Handling Strategies
1. Simple Exception Handling
try:
result = risky_operation()
except SpecificException as e:
## Handle specific exception
print(f"An error occurred: {e}")
2. Multiple Exception Handling
try:
## Potentially risky code
value = perform_calculation()
except ValueError as ve:
## Handle value-related errors
print(f"Value Error: {ve}")
except TypeError as te:
## Handle type-related errors
print(f"Type Error: {te}")
except Exception as e:
## Catch-all for unexpected errors
print(f"Unexpected error: {e}")
Exception Handling Flow
graph TD
A[Try Block] --> B{Exception Occurs?}
B -->|Yes| C[Match Specific Exception]
B -->|No| D[Continue Execution]
C --> E[Execute Except Block]
E --> F[Optional Finally Block]
D --> F
Advanced Exception Handling Patterns
Context Manager Pattern
class ResourceManager:
def __enter__(self):
## Setup resource
return self
def __exit__(self, exc_type, exc_value, traceback):
## Cleanup resource
if exc_type is not None:
print(f"An error occurred: {exc_value}")
return False ## Propagate exceptions
## Usage
with ResourceManager() as resource:
## Perform operations
pass
Exception Handling Best Practices
Pattern |
Description |
Recommendation |
Specific Exceptions |
Catch specific exceptions |
Preferred over broad exception handling |
Logging |
Log exceptions for debugging |
Use Python's logging module |
Cleanup |
Always release resources |
Use finally or context managers |
Reraise |
Reraise after logging or partial handling |
Preserve original exception |
Logging and Reraising Exceptions
import logging
def complex_operation():
try:
## Risky operation
result = perform_critical_task()
except SpecificException as e:
## Log the exception
logging.error(f"Operation failed: {e}")
## Reraise the exception
raise
return result
Custom Error Handling Decorator
def error_handler(func):
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except ValueError as ve:
print(f"Value Error in {func.__name__}: {ve}")
except Exception as e:
print(f"Unexpected error in {func.__name__}: {e}")
return wrapper
@error_handler
def divide_numbers(a, b):
return a / b
Practical Exception Chaining
try:
## Primary operation
primary_result = main_operation()
except PrimaryException as e:
try:
## Fallback operation
fallback_result = alternative_operation()
except FallbackException as fe:
## Log and handle chained exceptions
raise RuntimeError("Both primary and fallback operations failed") from fe
By mastering these exception handling patterns, you can create more robust and maintainable Python code. LabEx encourages developers to think strategically about error management and implement comprehensive exception handling techniques.