Introduction
Custom exceptions in Python allow you to define your own error types that can be raised and caught in the same way as built-in exceptions. This is useful when you want to create specific error conditions for your application, making your code more readable and maintainable.
Key Concepts
- Custom Exception Class: Create a new exception class by inheriting from the built-in
Exception
class or any of its subclasses. - Raising Custom Exceptions: Use the
raise
keyword to generate a custom exception. - Handling Custom Exceptions: Use
try
,except
blocks to catch and handle custom exceptions.
Basic Syntax
Defining a Custom Exception
class CustomError(Exception):
"""Base class for other exceptions"""
pass
Raising a Custom Exception
def example_function(value):
if value < 0:
raise CustomError("Negative value not allowed.")
Handling a Custom Exception
try:
example_function(-1)
except CustomError as e:
print(e)
Output
Negative value not allowed.
Creating a Custom Exception with Attributes
You can add custom attributes to your exception class to provide more context about the error.
Example
class CustomError(Exception):
def __init__(self, message, value):
self.message = message
self.value = value
super().__init__(self.message)
try:
raise CustomError("An error occurred", 42)
except CustomError as e:
print(f"{e.message}: {e.value}")
Output
An error occurred: 42
Real-World Example: ValidationError
Let’s consider a real-world example where we create a custom exception ValidationError
for validating user input.
Defining a Custom Exception
class ValidationError(Exception):
def __init__(self, message, field):
self.message = message
self.field = field
super().__init__(self.message)
def __str__(self):
return f"Validation error in '{self.field}': {self.message}"
Using the Custom Exception
def validate_age(age):
if age < 0 or age > 120:
raise ValidationError("Age must be between 0 and 120.", "age")
return True
try:
validate_age(150)
except ValidationError as e:
print(e)
Output
Validation error in 'age': Age must be between 0 and 120.
Nested Custom Exceptions
You can create a hierarchy of custom exceptions by defining multiple custom exception classes.
Example
class ApplicationError(Exception):
"""Base class for other exceptions"""
pass
class InputError(ApplicationError):
def __init__(self, message, field):
self.message = message
self.field = field
super().__init__(self.message)
def __str__(self):
return f"Input error in '{self.field}': {self.message}"
class ProcessingError(ApplicationError):
def __init__(self, message, step):
self.message = message
self.step = step
super().__init__(self.message)
def __str__(self):
return f"Processing error in '{self.step}': {self.message}"
Using Nested Custom Exceptions
def process_data(data):
if not isinstance(data, dict):
raise InputError("Data must be a dictionary.", "data")
if "key" not in data:
raise ProcessingError("Missing 'key' in data.", "process_data")
return True
try:
process_data(["invalid", "data"])
except ApplicationError as e:
print(e)
Output
Input error in 'data': Data must be a dictionary.
Conclusion
Custom exceptions in Python allow you to create specific error conditions tailored to your application’s needs. By defining custom exception classes, you can provide more meaningful error messages and handle errors more effectively. This enhances code readability and maintainability. Understanding how to create, raise, and handle custom exceptions is essential for writing robust and user-friendly Python applications.