Define Custom Exceptions in Python

Last Updated : 27 Jun, 2026

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.

Python
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.

  1. Better Readability: Makes error messages more meaningful and easier to understand.
  2. Application-Specific Handling: Helps represent errors related to your business logic or application rules.
  3. Easier Debugging: Makes it easier to identify and handle specific error conditions.
  4. 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.

Python
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.

Python
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.

Python
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.

Python
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.

Python
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.
Comment