User-Defined Exception in Python
Overview
While writing real-life programs for various applications, we must put constraints on the variables of use. For instance, in Date-of-birth, a month cannot be greater than 12 nor be negative, or the social media username must not contain a space character. To handle these sensitive values and to force them to be of a specific format, we use user-defined exceptions in Python. These user-defined exceptions can be derived from the superclass of Exception(Multiple Inheritance), used as a normal Python class, or implemented using Standard Exceptions such as Runtime Exception.
User-Defined Exceptions in Python
Python detects all the critical errors that occur during Compile-time and Runtime. It stops the program's execution if the error occurs and raises an exception. Some commonly raised Exceptions are ArithmeticError, AttributeError, ImportError, IOError, FileNotFoundError, etc.
Sometimes we must enforce constraints on the values that specific program variables can take or save the program from running into an undesired state. In such situations, Python allows programmers to create User-defined Exceptions. To create a User-defined Exception, we need to create a class directly or indirectly derived from the built-in Exception class.
Let us see how we can create our exception in python:
Creating Exception Class
Our Exception class should Implement Exceptions to raise exceptions. In this exception class, we can either put pass or give an implementation. Let us define init function.
Code:
In the example above, JustException is a user-defined Exception. This class implements the Exception class. We have defined the __init__ function that takes the message of the String type as a parameter and prints the message. This JustException class can implement everything like a normal class in Python.
Raising User-defined Exception
When a certain condition is met, we use the raise keyword to throw an exception. To raise a User-defined Exception, we can do the following:
Code:
The raise keyword raises the exception mentioned after it. In this case, JustException is raised.
Output:
Explanation:
As we can see, the message we passed to the __init__ class is displayed in the exception and output.
Catching Exception
As a usual exception, this exception can be handled using the try-except block.
Code:
Output:
Explanation:
In the try block, we are raising the exception with the message. This message is printed from the __init__ function. In except block, we print the message rather than ending the program in an undesired state.
Example of Creating User-Defined Exception in Python
Let us take an example of a program used to enroll students in a particular course. To decide which students can enroll, there is a cut-off and maximum score. If a student's percentage is in the acceptable range, they are enrolled, or else an exception is raised. In this case, no student enrolling should have a percentage less than the cut-off as well as their score cannot be higher than the maximum score.
Code:
Output:
Explanation:
- PercentageError class is a base class that implements the Python Exception class. This class can be implemented by the other Exception classes. We use pass as syntactically some statement is required but we don't want to enter any command in it.
- InvalidPercentageError Exception is raised if the percentage value is greater than 100. LessPercentageError Exception is raised if the percentage value is less than the cut-off range. Both these classes have Initializers that send respective messages to the superclass.
- checkPercentage class has an Initializer (Constructor) function that takes the percentage argument as per. It raises exception incase if per is not in desired range i.e InvalidPercentageError if greater than 100 or LessPercentageError if less than 80. We use the try-except block to see the output in all the 3 cases.
More Examples
Example 1: Deriving Error from Super Class Exception (Multiple Inheritance)
It is a good practice to use a base Exception class in the case of a single module handling multiple several distinct errors. This base class can further be implemented by various other user-defined classes to address different errors.
Let us create a class that is used for signing up. Here we will ensure that the password contains only numbers, small characters, and capital characters. Also, we will ask the user to enter the password again for confirmation.
Code:
Output 1: The first input is for an invalid character error.
Output 2: The second input is for Passwords that do not match error
Explanation:
In the example above, there can be multiple cases where the password is invalid. We have taken 2 cases, the first one is if the password contains any invalid characters, and the second one is if the password does not match the confirmation password. We create a base class that implements the Exception class.
The other two error classes further implement this base class. We check each character one by one. If the character is invalid CharacterError exception is raised. We ask the user to enter the password again if the password is valid. If both the passwords do not match DifferentPasswordsError exception is raised.
Example 2: Customizing Exception Classes
Exception class is just like any normal class. Thus, we can customize this class as per our requirements, like giving multiple arguments to its constructor.
For example, consider a voting system. It takes various details of the person as well as checks if all the values entered are appropriate. Here, we are trying to create a class that performs this task as well as throws an exception in case the age of the person is less than 18.
Code:
Output:
Explanation:
The initializer of VotingPerson takes 3 parameters name, id, and age. In the try block, we take user input for all three values. If the age is less than 18 it raises an Error which is caught by except block. Else it creates an object of VotingPerson.
Example 3: Creating a User-defined Exception class (Standard Exceptions)
When some errors don't fall into any categories already defined, the Runtime Error class is a standard exception that can be raised. Thus exceptions can be derived from Standard Exceptions as the base class.
Let us take an example of a User-defined Runtime Exception. Say we have a list of users and their addresses. We try to fetch the name using the address. If the address doesn't exist UserNotFound Exception is raised else, it will display the name of the user.
Code:
Output:
Explanation:
UserNotFound is an Exception class that implements RuntimeError class. logBook is of Dictionary type, which stores the record of addresses and names of the users. Login class has a function that searches for the record in the logBook. If the record exists, it displays the name. Else it raises an error. We fetch the names of 2 addresses in the try block, out of which one exists, and the other doesn't. So it displays the name for the first address and raises an exception for the second one.
Conclusion
- User-defined exceptions are created to force certain constraints on the values of the variables. To create a User-defined Exception, we have to create a class that implements the Exception class.
- We can raise(throw) these exceptions using the raise keyword. These exceptions can be caught in the try-except block, just like common exceptions.
- In some conditions, we have multiple errors to handle in the same class. In such situations, we create a base class, which is further implemented by other Exception classes.
- Classes implementing Exceptions are the same as normal classes. Thus they can be customized and used as one.
- We can also use Standard Exception classes for implementation where the error doesn't seem to fall into any particular category.