Custom Exceptions in Python
Python allows developers to define their own exceptions by creating custom exception classes. This is useful when the built-in exceptions do not cover specific error scenarios in your application. Custom exceptions provide a more descriptive and meaningful way to handle errors.
Defining a Custom Exception
To create a custom exception, you define a new class that inherits from Python's built-in Exception class. Here is the basic structure:
class CustomException(Exception):
pass
By inheriting from Exception, the custom class becomes a valid exception that can be raised and handled using try and except.
Example 1: Basic Custom Exception
class CustomError(Exception):
pass
try:
raise CustomError("This is a custom error")
except CustomError as e:
print(f"Caught an exception: {e}")
In this example, the CustomError exception is raised with a custom error message and handled in the except block.
Adding Custom Attributes
You can add custom attributes to your exception class to store additional information about the error.
Example 2: Custom Exception with Attributes
class InvalidInputError(Exception):
def __init__(self, value, message="Invalid input provided"):
self.value = value
self.message = message
super().__init__(self.message)
try:
raise InvalidInputError("abc", "Input must be a number")
except InvalidInputError as e:
print(f"Error: {e.message}. Value: {e.value}")
Here, the custom exception stores the invalid value and a detailed message, making the error handling more informative.
Customizing the String Representation
You can override the __str__ method in your custom exception class to define a custom string representation for the error.
Example 3: Overriding the String Representation
class DivisionError(Exception):
def __init__(self, numerator, denominator):
self.numerator = numerator
self.denominator = denominator
def __str__(self):
return f"Cannot divide {self.numerator} by {self.denominator}"
try:
raise DivisionError(10, 0)
except DivisionError as e:
print(e)
In this example, the __str__ method customizes the error message, providing a clear explanation of the error.
Using Custom Exceptions in Functions
Custom exceptions are especially useful in functions to validate input or enforce business logic.
Example 4: Custom Exception in a Function
class AgeError(Exception):
pass
def validate_age(age):
if age < 0:
raise AgeError("Age cannot be negative")
print(f"Valid age: {age}")
try:
validate_age(-5)
except AgeError as e:
print(f"Validation error: {e}")
Here, the AgeError exception is raised if the provided age is negative, ensuring that the input is validated before proceeding.
Subclassing Custom Exceptions
You can create a hierarchy of exceptions by subclassing your custom exception class. This is useful for grouping related errors.
Example 5: Exception Hierarchy
class ApplicationError(Exception):
pass
class DatabaseError(ApplicationError):
pass
class FileNotFoundError(ApplicationError):
pass
try:
raise DatabaseError("Database connection failed")
except ApplicationError as e:
print(f"Application error: {e}")
In this example, DatabaseError and FileNotFoundError are subclasses of ApplicationError. The exception hierarchy allows you to catch specific errors or general application errors.
Key Points
- Custom exceptions are created by inheriting from the
Exceptionclass. - You can add attributes and methods to provide additional error details.
- Custom exceptions make your code more descriptive and easier to debug.
- Exception hierarchies help in organizing and handling related errors efficiently.
Conclusion
Custom exceptions are a powerful feature in Python that allow you to define and handle application-specific errors in a clear and meaningful way. By using custom exception classes, you can make your code more robust, maintainable, and user-friendly.