Crafting Exceptions
Creating Custom Exceptions
Defining Custom Exception Classes
class CustomValidationError(Exception):
"""Custom exception for validation errors"""
def __init__(self, message, error_code=None):
self.message = message
self.error_code = error_code
super().__init__(self.message)
def validate_age(age):
if age < 0:
raise CustomValidationError("Age cannot be negative", error_code=400)
if age > 120:
raise CustomValidationError("Invalid age", error_code=401)
return age
## Usage example
try:
validate_age(-5)
except CustomValidationError as e:
print(f"Error: {e.message}")
print(f"Error Code: {e.error_code}")
Exception Hierarchy and Design
graph TD
A[BaseException] --> B[Exception]
B --> C[Custom Base Exception]
C --> D[Specific Custom Exception 1]
C --> E[Specific Custom Exception 2]
Advanced Exception Techniques
Exception Chaining
def complex_operation():
try:
## Some operation that might fail
result = perform_risky_calculation()
except ValueError as original_error:
raise RuntimeError("Calculation failed") from original_error
Exception Attributes and Methods
Attribute/Method |
Description |
args |
Tuple of arguments passed to the exception |
__str__() |
Returns a string representation of the exception |
with_traceback() |
Allows setting a custom traceback |
Contextual Exception Handling
class DatabaseConnectionError(Exception):
def __init__(self, message, connection_details=None):
self.message = message
self.connection_details = connection_details
super().__init__(self.message)
def connect_to_database(host, port):
try:
## Simulated database connection
if not is_valid_connection(host, port):
raise DatabaseConnectionError(
"Failed to connect to database",
connection_details={'host': host, 'port': port}
)
except DatabaseConnectionError as e:
print(f"Connection Error: {e.message}")
print(f"Connection Details: {e.connection_details}")
Best Practices for Custom Exceptions
- Inherit from the base
Exception
class
- Provide clear and descriptive error messages
- Include additional context when possible
- Keep exceptions specific and focused
LabEx Insight
When developing custom exceptions, LabEx recommends creating a clear and meaningful exception hierarchy that reflects your application's specific error scenarios.
## Efficient exception handling
def process_data(data):
try:
## Complex processing logic
return process_complex_data(data)
except (ValueError, TypeError) as e:
## Efficient multi-exception handling
log_error(e)
return None