Raising and Handling Exceptions
Custom exceptions are user-defined classes that inherit from Exception, enabling you to represent errors specific to your application's domain.
Why Generic Errors Are Not Always Enough
Python provides built-in exceptions such as ValueError and TypeError for common problems. However, an application often has conditions that are specific to its own rules. A text-input validator, for example, may need to represent the condition that an input is too short. A custom exception gives that condition a clear name instead of forcing it into a generic error category.
A custom exception is a user-defined class that inherits from Exception and represents an error specific to an application's domain.
Defining the Exception Class
Define a custom exception by creating a class whose superclass is Exception. The class name describes the application condition that the exception represents. A minimal class can contain pass, meaning that it adds no methods or attributes beyond what it inherits from Exception.
The inheritance chain from BaseException through Exception to ShortInputException makes the custom exception compatible with Python's exception-handling system. It can be handled by an except block that catches the custom type, Exception, or BaseException.
Storing Useful Error Details
A custom exception becomes more useful when it carries information about the problem. Add an __init__ method to store relevant details as instance attributes. In the ShortInputException example, the exception stores the actual input length and the minimum length required.
The __init__ method receives length and atleast as arguments. It calls Exception.__init__(self) to initialize the parent Exception class, then stores the two values as instance attributes. Code that catches the exception can later read those attributes and respond to the exact error details.
Store details that help the handler explain what went wrong or make a decision based on the specific error.
Following Control After raise
Use the raise statement to create and throw an exception. The exception class name follows raise, along with the arguments required by its __init__ method. When the raise statement executes, normal execution stops at that point. Control immediately moves to the nearest enclosing try-except block that can handle the exception type.
class ShortInputException(Exception): def __init__(self, length, atleast): Exception.__init__(self) self.length = length self.atleast = atleast text = "hi" try: if len(text) < 3: raise ShortInputException(len(text), 3) except ShortInputException as error: print(error.length) print(error.atleast)
2
3Handling the Domain Condition
Validating a Minimum Input Length
Represent an input shorter than three characters with a custom exception and handle the stored details.
Define the exception: Create ShortInputException as a subclass of Exception. Give it an __init__ method that stores the actual length and required minimum.
Check the input: Inside a try block, compare the input length with the minimum of 3.
Raise the custom type: If the length is too short, raise ShortInputException and pass the actual length and 3 as arguments.
Handle the condition: Catch ShortInputException with as and use the exception object's length and atleast attributes to provide specific feedback.
Handle successful input: If the input has at least 3 characters, the error is not raised and the else path can confirm successful input.
The program distinguishes the domain-specific condition of input being too short from other possible errors and gives the handler the exact values it needs.
Input acceptedWith the input set to hello, the length is at least 3, so the raise statement does not execute. The except block is skipped and the else block confirms successful input. If the input contained fewer than 3 characters, the custom exception would be raised and the handler would use its stored length and atleast values.
Mistakes with Custom Exceptions
Defining the custom class without inheriting from Exception
The custom class is not connected to Exception through the inheritance chain described for Python exception handling.
Fix:
Define it as class ShortInputException(Exception):Raising the exception without the arguments required by __init__
The example exception's __init__ method expects the actual length and the minimum length.
Fix:
Pass both values, such as raise ShortInputException(len(text), 3).Catching the exception but ignoring its stored details
The handler misses the length and atleast attributes that can make the feedback more specific.
Fix:
Bind the object with as and access its attributes, such as except ShortInputException as error.Expecting execution to continue after raise inside the try block
When raise executes, control immediately moves to the nearest enclosing try-except block that can handle the exception.
Fix:
Place handling logic in the matching except block.
Practice and Recall
What do you think happens?
In the input-validation example, what happens when text is set to "hi" and the minimum is 3?
Reveal answer
Answer: ShortInputException is raised and the except block handles it.
The input length is less than the required minimum. The raise statement creates the custom exception with the actual length and minimum, and control moves to the matching except block.
Design a custom exception for a domain-specific condition in a program. Give the class a name that describes the condition, decide whether the handler needs stored details, and identify the arguments that the raise statement should provide.
Hints
- Begin with a class that inherits from Exception.
- If the handler needs details, store them as instance attributes in __init__.
- Make the arguments supplied to raise match the parameters expected by __init__.
- Catch the custom type with an except block and use as to access the exception object.
Key Takeaways
- A custom exception is a user-defined class that inherits from Exception.
- A minimal custom exception can use pass, while an __init__ method can store useful error details.
- The raise statement creates the custom exception and passes arguments to its __init__ method.
- When raise executes, control moves to the nearest matching try-except handler.
- Custom exceptions make domain-specific error conditions clearer and allow handlers to provide targeted responses.
Key Takeaways
- Custom exceptions represent application-specific error conditions.
- They inherit from Exception and therefore fit into Python's exception-handling hierarchy.
- An __init__ method can store details such as the actual input length and required minimum.
- raise transfers control to a matching except block, where the handler can access the exception object's data.