Introduction

In Python, exceptions are used to handle errors that occur during the execution of a program. While Python provides several built-in exceptions, you can also create your custom exceptions to handle specific situations. Custom exceptions allow you to define your error-handling logic and make your code more readable and maintainable.

This guide shows you how to use custom exceptions in Python.

Prerequisites

Before you begin:

  • Deploy a VPS server. For instance, Ubuntu 24.04.
  • Create a non-root sudo user.
  • Install Python

Declare Python Custom Exceptions

Creating custom exceptions in Python involves defining a new class that inherits from the built-in Exception class. This allows you to create your own error messages and handle specific types of errors more gracefully.

Here's a basic syntax:

Python
class CustomError(Exception):
    """Custom exception class"""
    def __init__(self, message):
        self.message = message
        super().__init__(self.message)

Example:

Python
class NegativeNumberError(Exception):
    """Exception raised for errors in the input if the number is negative."""

    def __init__(self, value):
        self.value = value
        self.message = f"{value} is a negative number, which is not allowed."
        super().__init__(self.message)

def check_positive(number):
    if number < 0:
        raise NegativeNumberError(number)
    return True

try:
    check_positive(-5)
except NegativeNumberError as e:
    print(e)

In this example, the NegativeNumberError exception is raised if the input number is negative, and a custom error message is displayed.

Combine Multiple Exceptions

You can handle multiple exceptions in your code by using a combination of built-in and custom exceptions. This allows you to create more comprehensive error-handling logic.

Example:

Python
class InvalidAgeError(Exception):
    """Exception raised for errors in the input age."""

    def __init__(self, age):
        self.age = age
        self.message = f"{age} is not a valid age."
        super().__init__(self.message)

def check_age(age):
    if not isinstance(age, int):
        raise TypeError("Age must be an integer")
    if age < 0 or age > 120:
        raise InvalidAgeError(age)
    return True

try:
    check_age("twenty")
except (TypeError, InvalidAgeError) as e:
    print(e)

In this example, the check_age function raises a TypeError if the input is not an integer and raises an InvalidAgeError if the age is out of the valid range. Both exceptions are handled in the try block.

Nested Exceptions

Sometimes, you may need to handle exceptions within other exceptions. This can be achieved using nested try blocks.

Example:

Python
class FileError(Exception):
    """Exception raised for errors related to file operations."""

    def __init__(self, filename):
        self.filename = filename
        self.message = f"Error with file: {filename}"
        super().__init__(self.message)

def read_file(filename):
    try:
        with open(filename, 'r') as file:
            return file.read()
    except FileNotFoundError:
        raise FileError(filename)

try:
    try:
        content = read_file("non_existent_file.txt")
    except FileError as e:
        print(e)
        # Nested try block
        try:
            content = read_file("backup_file.txt")
        except FileError as e:
            print(e)
except Exception as e:
    print("An unexpected error occurred:", e)

In this example, the read_file function raises a FileError if the file is not found. The nested try block attempts to read from a backup file if the first file is not found.

Implement Python Custom Exceptions Best Practices

When creating and using custom exceptions, follow these best practices:

  • Meaningful Names: Use descriptive names for custom exceptions to indicate the type of error.
  • Documentation: Provide docstrings to explain the purpose of the custom exception.
  • Inherit from Exception: Always inherit custom exceptions from the built-in Exception class.
  • Avoid Overuse: Use custom exceptions sparingly and only when necessary to avoid cluttering your code.
  • Custom Messages: Include meaningful error messages to help debug issues.

Example with meaningful names and documentation:

Python
class ZeroDivisionError(Exception):
    """Exception raised for division by zero."""

    def __init__(self, message="Cannot divide by zero"):
        self.message = message
        super().__init__(self.message)

def divide(a, b):
    if b == 0:
        raise ZeroDivisionError()
    return a / b

try:
    divide(10, 0)
except ZeroDivisionError as e:
    print(e)

This example raises a ZeroDivisionError with a custom message when attempting to divide by zero.

Discover Custom Exceptions Practical Use Cases

Custom exceptions are useful in various real-world scenarios:

  • Validation: Raise custom exceptions for invalid input data.
  • API Errors: Handle API-related errors with custom exceptions.
  • File Operations: Manage file-related errors, such as missing or corrupted files.
  • Database Operations: Handle database errors, such as connection issues or query failures.
  • Business Logic: Implement business-specific error handling, such as invalid transactions.

Example for validation:

Python
class InvalidEmailError(Exception):
    """Exception raised for invalid email addresses."""

    def __init__(self, email):
        self.email = email
        self.message = f"{email} is not a valid email address."
        super().__init__(self.message)

def validate_email(email):
    if "@" not in email or "." not in email:
        raise InvalidEmailError(email)
    return True

try:
    validate_email("invalid-email")
except InvalidEmailError as e:
    print(e)

This example raises an InvalidEmailError if the email address is invalid.

Conclusion

This guide explains how to create and use Python custom exceptions, including their syntax, combining multiple exceptions, nested logic, best practices, and practical use cases. Custom exceptions are crucial for handling specific errors in your code, making it more robust and maintainable. Understanding how to implement custom exceptions effectively can significantly improve your programming skills and the quality of your applications.