In Python, exceptions are used to handle errors during the execution of a program. While Python provides many built-in exceptions, sometimes you may need to define your own exceptions to represent specific error conditions in your application. This is where custom exceptions come in. Custom exceptions allow you to handle errors more effectively and improve code clarity.
What are Custom Exceptions?
Custom exceptions are user-defined exceptions that you can create by subclassing the built-in Exception
class. Custom exceptions are useful when you want to raise an error that is specific to your application, making it easier to identify and manage.
Creating a Custom Exception
To create a custom exception in Python, you need to define a new class that inherits from the built-in Exception
class. You can then add your own custom logic and messages to the exception.
Syntax:
class CustomException(Exception): def __init__(self, message): self.message = message super().__init__(self.message)
1. Example: Creating a Simple Custom Exception
Let’s create a custom exception that is raised when a user provides invalid input in a program.
Example:
class InvalidInputError(Exception): def __init__(self, message): self.message = message super().__init__(self.message) def validate_input(value): if value < 0: raise InvalidInputError("Input cannot be negative.") return f"Input {value} is valid." try: print(validate_input(-5)) except InvalidInputError as e: print(f"Error: {e}")
In this example, we define a custom exception InvalidInputError
and raise it when the user provides a negative value as input. The exception is then caught in the except
block and an appropriate error message is printed.
2. Adding Custom Attributes to Custom Exceptions
You can add custom attributes to your exception class to provide additional information about the error, such as an error code or a timestamp.
Example:
class AuthenticationError(Exception): def __init__(self, message, error_code): self.message = message self.error_code = error_code super().__init__(self.message) def authenticate_user(username, password): if username != "admin" or password != "password123": raise AuthenticationError("Invalid username or password.", 401) return "Authentication successful." try: print(authenticate_user("user", "pass")) except AuthenticationError as e: print(f"Error: {e.message} (Error code: {e.error_code})")
Here, we define an AuthenticationError
exception with an error_code
attribute. This gives us more flexibility to pass additional information when raising the exception, such as an HTTP error code.
3. Customizing Exception Messages
You can customize the error message when raising a custom exception to make the output more descriptive and easier to understand.
Example:
class InsufficientFundsError(Exception): def __init__(self, message, balance, amount): self.message = message self.balance = balance self.amount = amount super().__init__(self.message) def withdraw(balance, amount): if amount > balance: raise InsufficientFundsError("Insufficient funds for this transaction.", balance, amount) return balance - amount try: print(withdraw(100, 150)) except InsufficientFundsError as e: print(f"Error: {e.message}. Balance: {e.balance}, Requested amount: {e.amount}")
In this example, we define a custom exception InsufficientFundsError
that includes additional information such as the current balance and the requested withdrawal amount.
4. Handling Multiple Custom Exceptions
You can define multiple custom exceptions and handle them individually using multiple except
blocks. This allows you to implement specific logic for different error scenarios.
Example:
class FileNotFoundError(Exception): pass class PermissionDeniedError(Exception): pass def read_file(filename): if filename == "missing.txt": raise FileNotFoundError("File not found.") elif filename == "protected.txt": raise PermissionDeniedError("Permission denied.") return "File content" try: print(read_file("missing.txt")) except FileNotFoundError as e: print(f"Error: {e}") except PermissionDeniedError as e: print(f"Error: {e}")
Here, we define two custom exceptions, FileNotFoundError
and PermissionDeniedError
, and handle them separately using two different except
blocks. This allows us to respond to different types of errors in a more specific way.
Conclusion
Custom exceptions in Python are a powerful tool for handling specific error conditions in your application. By defining your own exceptions, you can make your code more readable, modular, and easier to debug. Whether you're validating user input, managing file access, or handling complex business logic, custom exceptions help you improve error handling and create a more robust application.