Effective Exception Handling
Best Practices for Exception Management
1. Specific Exception Handling
def read_data(filename):
try:
with open(filename, 'r') as file:
data = file.read()
except FileNotFoundError:
print(f"File {filename} not found")
except PermissionError:
print(f"No permission to read {filename}")
2. Exception Hierarchy and Handling Order
graph TD
A[Most Specific Exception] --> B[Less Specific Exception]
B --> C[Most General Exception]
3. Using else
and finally
Clauses
def process_data(data):
try:
result = complex_calculation(data)
except ValueError:
print("Invalid data")
else:
## Executed if no exception occurs
save_result(result)
finally:
## Always executed
cleanup_resources()
Advanced Exception Handling Techniques
Context Managers
class ResourceManager:
def __enter__(self):
## Setup resources
return self
def __exit__(self, exc_type, exc_value, traceback):
## Cleanup resources
if exc_type is not None:
print(f"Exception occurred: {exc_type}")
return False
with ResourceManager() as manager:
## Perform operations
Exception Logging
Logging Level |
Description |
DEBUG |
Detailed information |
INFO |
Confirmation of expected behavior |
WARNING |
Potential issue |
ERROR |
Serious problem |
CRITICAL |
Critical error |
import logging
logging.basicConfig(level=logging.ERROR)
def risky_operation():
try:
## Potentially problematic code
result = dangerous_calculation()
except Exception as e:
logging.error(f"Operation failed: {e}")
Custom Exception Design
class ValidationError(Exception):
def __init__(self, message, error_code=None):
self.message = message
self.error_code = error_code
super().__init__(self.message)
def validate_user_input(data):
if not data:
raise ValidationError("Empty input", error_code=400)
Exception Handling Patterns
1. Graceful Degradation
def fetch_data(primary_source, backup_source):
try:
return primary_source()
except ConnectionError:
return backup_source()
2. Retry Mechanism
def retry_operation(func, max_attempts=3):
attempts = 0
while attempts < max_attempts:
try:
return func()
except TransientError:
attempts += 1
time.sleep(1)
raise PermanentError("Operation failed after multiple attempts")
- Avoid using exceptions for flow control
- Catch only necessary exceptions
- Minimize code within
try
blocks
- Use logging for tracking errors
By implementing these strategies, you'll create more robust and maintainable Python code with LabEx's advanced programming techniques.