CodeGym /Courses /Python SELF EN /Creating Your Own Exception

Creating Your Own Exception

Python SELF EN
Level 18 , Lesson 1
Available

7.1 Creating Custom Exceptions

Sometimes the standard Python exceptions don't fully meet the needs of your application. In such cases, you can create your own exceptions, inheriting them from the base class Exception or any other suitable exception class.

Basics of Creating Custom Exceptions

Creating a custom exception involves defining a new class that inherits from the base class Exception. You can add your own methods and attributes to your exception class to provide additional information about the error.

Example of a simple custom exception creation

Step 1: Define the Custom Exception


class MyCustomError(Exception):
    """Class for custom exception."""
    pass
        

Step 2: Use the Custom Exception


def check_value(value):
    if value < 0:
        raise MyCustomError("Value must not be less than zero")
            
try:
    check_value(-1)
except MyCustomError as e:
    print(f"A custom exception occurred: {e}")
            

It's pretty simple. The main point is that your exception should inherit from the Exception class or one of its descendants.

7.2 Creating an Exception with Additional Attributes

You can add attributes and methods to your exception class to pass additional information about the occurred error.

Example:


class NegativeValueError( Exception ):
    """Class for custom exception when value is negative."""
    def __init__(self, value, message = "Value must not be less than zero"):
        self.value = value
        self.message = message
        super().__init__(self.message)

    def __str__(self):
        return f'{self.message}: {self.value}'

Using the Exception with Additional Attributes


def check_value(value):
    if value < 0:
        raise NegativeValueError(value)

try:
    check_value(-1)
except NegativeValueError as e:
    print(f"A custom exception occurred: {e}")

Our exception is a class that is inherited from the Exception class. So you can do everything with it as with any other class: add fields, methods, constructor parameters, etc.

All for your convenience, and the convenience of those programmers who will be catching your exceptions.

7.3 Creating a Hierarchy of Custom Exceptions

For more complex applications, it's useful to create hierarchies of custom exceptions. This allows you to group related exceptions and simplify their handling.

Example:


class ApplicationError(Exception):
    """Base class for all application exceptions."""
    pass

class NegativeValueError(ApplicationError):
    """Class for custom exception when value is negative."""
    def __init__(self, value, message="Value must not be less than zero"):
        self.value = value
        self.message = message
        super().__init__(self.message)

    def __str__(self):
        return f'{self.message}: {self.value}'

class ValueTooLargeError(ApplicationError):
    """Class for custom exception when value is too large."""
    def __init__(self, value, message="Value is too large"):
        self.value = value
        self.message = message
        super().__init__(self.message)

    def __str__(self):
        return f'{self.message}: {self.value}'

Using the Hierarchy of Custom Exceptions


def check_value(value):
    if value < 0:
        raise NegativeValueError(value)
    elif value > 100:
        raise ValueTooLargeError(value)

try:
    check_value(150)
except NegativeValueError as e:
    print(f"An exception occurred: {e}")
except ValueTooLargeError as e:
    print(f"An exception occurred: {e}")
except ApplicationError as e:
    print(f"General application exception: {e}")

7.4 Order of Exception Handling

When handling exceptions, especially from one hierarchy, it's important to specify their correct order. Even though the code inside except blocks never executes simultaneously, it's all about the fact that the base exception class is able to catch exceptions of all descendant classes.

For example, the code:


def check_value(value):
    if value < 0:
        raise NegativeValueError(value)
    elif value > 100:
        raise ValueTooLargeError(value)
    
try:
    check_value(150)
except ApplicationError as e: # will catch exceptions of type ApplicationError and all its descendants
    print(f"General application exception: {e}")

In the except block, exceptions of type ApplicationError and all its descendant classes will be caught.

And since all exceptions are descendants of the Exception class, such code will catch all exceptions:


def check_value(value):
    if value < 0:
        raise NegativeValueError(value)
    elif value > 100:
        raise ValueTooLargeError(value)
    
try:
    check_value(150)
except Exception as e:
    print(f"Catching all exceptions: {e}")
except ApplicationError as e: # This code will never execute
    print(f"General application exception: {e}")

Catching exceptions in the except ApplicationError block will never happen because the except Exception block will catch all exceptions of type Exception and its descendants.

Solution

Therefore, it is customary to catch exceptions in the reverse order of inheritance: the closer the class is to the Exception class, the lower it is.

Example:


def check_value(value):
    if value < 0:
        raise NegativeValueError(value)
    elif value > 100:
        raise ValueTooLargeError(value)
        
try:
    check_value(150)
except NegativeValueError as e:
    print(f"An exception occurred: {e}")
except ApplicationError as e:
    print(f"General application exception: {e}")
except Exception as e:
    print(f"Catching all exceptions: {e}")

In this example, the except blocks are arranged in an order that matches their inheritance hierarchy: first, more specific exceptions like NegativeValueError are caught, then more general ones like ApplicationError. This allows for proper exception handling and avoids situations where a more general handler catches an exception before more specialized except blocks can handle it.

2
Task
Python SELF EN, level 18, lesson 1
Locked
Custom Exception
Custom Exception
2
Task
Python SELF EN, level 18, lesson 1
Locked
Hierarchy of Custom Exceptions
Hierarchy of Custom Exceptions
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION