In Python, exceptions are errors that occur while a program is running. Python provides many built-in exceptions, such as ZeroDivisionError, TypeError and ValueError, which can be handled using try and except blocks.
try:
result = 10 / 0
except ZeroDivisionError:
print("You cannot divide by zero!")
Output
You cannot divide by zero!
Explanation: When 10/0 is executed, Python raises a ZeroDivisionError. The except ZeroDivisionError block catches the exception and displays a user-friendly message instead of stopping the program.
Why Create Custom Exceptions?
Custom exceptions allow you to define application-specific errors that are not covered by Python's built-in exceptions.
- Better Readability: Makes error messages more meaningful and easier to understand.
- Application-Specific Handling: Helps represent errors related to your business logic or application rules.
- Easier Debugging: Makes it easier to identify and handle specific error conditions.
- Code Reusability: Custom exception classes can be reused throughout the application.
Creating a Custom Exception
To create a custom exception, define a class that inherits from Python's built-in Exception class.
class MyCustomError(Exception):
"""Exception raised for custom error scenarios."""
def __init__(self, message):
self.message = message
super().__init__(self.message)
Explanation:
- MyCustomError inherits from Exception.
- The message parameter stores details about the error.
- super().__init__(message) passes the message to the base exception class.
Adding Custom Attributes to an Exception
Custom exceptions can include additional information to provide more context about an error.
class MyCustomError(Exception):
def __init__(self, message, error_code):
super().__init__(message)
self.message = message
self.error_code = error_code
def __str__(self):
return f"{self.message} (Error Code: {self.error_code})"
err = MyCustomError("Invalid operation", 400)
print(err)
Output
Invalid operation (Error Code: 400)
Explanation:
- error_code stores additional information about the error.
- __str__() customizes how the exception is displayed.
- Printing the exception shows both the message and error code.
Raising a Custom Exception
Use the raise keyword to generate a custom exception when a specific condition occurs.
class MyCustomError(Exception):
pass
def divide(a, b):
if b == 0:
raise MyCustomError("Division by zero is not allowed")
return a / b
divide(10, 0)
Output
ERROR!
Traceback (most recent call last):
File "<main.py>", line 9, in <module>
File "<main.py>", line 6, in divide
MyCustomError: Division by zero is not allowed
Explanation:
- raise MyCustomError(...) creates and raises a custom exception.
- The exception is generated when b is 0.
- Since it is not handled, Python displays the error message and stops execution.
Handling a Custom Exception
Custom exceptions can be handled using a try-except block, just like built-in exceptions.
class MyCustomError(Exception):
pass
def divide(a, b):
if b == 0:
raise MyCustomError("Division by zero is not allowed")
return a / b
try:
result = divide(10, 0)
except MyCustomError as e:
print(f"Caught an error: {e}")
Output
Caught an error: Division by zero is not allowed
Explanation:
- divide() raises MyCustomError when b is 0.
- The except MyCustomError block catches the exception.
- The program continues running instead of terminating abruptly.
Custom Exception with Additional Context
Custom exceptions can store extra details that help identify the exact source of an error.
class FileProcessingError(Exception):
def __init__(self, message, filename, lineno):
super().__init__(message)
self.message = message
self.filename = filename
self.lineno = lineno
def __str__(self):
return f"{self.message} in {self.filename} at line {self.lineno}"
try:
raise FileProcessingError("Syntax error", "example.txt", 13)
except FileProcessingError as e:
print(f"Caught an error: {e}")
Output
Caught an error: Syntax error in example.txt at line 13
Explanation:
- filename and lineno provide additional details about the error.
- __str__() formats the error message using all stored information.
- This makes debugging easier by identifying where the problem occurred.
Tips for Using Custom Exceptions
- Use descriptive names: Names such as ValidationError or FileProcessingError clearly indicate the type of problem.
- Add docstrings: Document when and why the exception should be used.
- Create exception hierarchies: Use a base custom exception when an application has multiple related error types.
- Store useful details: Include additional attributes when they help identify or debug errors.