In this tutorial, we will learn how we can create our own customized and user-defined exceptions in Python.
1. What are exceptions and how to handle them?
To know more about
exceptions in Python and how we can handle them using several keywords like
raise, go through this tutorial.
Now we have knowledge of how to use these keywords and built-in Exceptions in our code to handle them. But there are chances that software may require exceptions other than the built-in ones and developer has to define own exceptions according to the requirement. In such scenarios, we create our own Exception classes and handle them similarly as we handle built-in exceptions. Let’s look at the hierarchy of built-in exceptions in Python before creating our own exceptions.
2. Built-in Exceptions Class hierarchy
BaseException +-- SystemExit +-- KeyboardInterrupt +-- GeneratorExit +-- Exception # Base Class of all exceptions +-- StopIteration +-- StopAsyncIteration +-- ArithmeticError | +-- FloatingPointError | +-- OverflowError | +-- ZeroDivisionError +-- AssertionError +-- AttributeError +-- BufferError +-- EOFError +-- ImportError | +-- ModuleNotFoundError +-- LookupError | +-- IndexError | +-- KeyError +-- MemoryError +-- NameError | +-- UnboundLocalError +-- OSError | +-- BlockingIOError | +-- ChildProcessError | +-- ConnectionError | | +-- BrokenPipeError | | +-- ConnectionAbortedError | | +-- ConnectionRefusedError | | +-- ConnectionResetError | +-- FileExistsError | +-- FileNotFoundError | +-- InterruptedError | +-- IsADirectoryError | +-- NotADirectoryError | +-- PermissionError | +-- ProcessLookupError | +-- TimeoutError +-- ReferenceError +-- RuntimeError | +-- NotImplementedError | +-- RecursionError +-- SyntaxError | +-- IndentationError | +-- TabError +-- SystemError +-- TypeError +-- ValueError | +-- UnicodeError | +-- UnicodeDecodeError | +-- UnicodeEncodeError | +-- UnicodeTranslateError +-- Warning +-- DeprecationWarning +-- PendingDeprecationWarning +-- RuntimeWarning +-- SyntaxWarning +-- UserWarning +-- FutureWarning +-- ImportWarning +-- UnicodeWarning +-- BytesWarning +-- ResourceWarning
3. Creating User-defined Exceptions Classes
From the above hierarchy, we have seen that base class of almost all exceptions in Python directly or indirectly is the class
Exception and if we want to create our own exception, we have to inherit this Exception class or its subclasses in the newly created custom exception class.
3.1 Creating a simple user-defined exception class
Lets defined a simple custom exception class by deriving in-built
Exception class and raise the exception by using the
class CustomException(Exception): pass raise CustomException("Message related to exception")
Traceback (most recent call last): File "cutomexcp.py", line 4, in raise CustomException("Message related to exception") __main__.CustomException: Message related to exception
3.2 Creating a user-defined exception class using magic methods
To define a custom exception class, we generally use two
__str__(), __init__() is a constructor of a class that will be called automatically when an object of that class is created and __str__() is automatically called whenever the object is to be printed. So we will modify these two magic methods according to the requirements.
Scenario: Suppose we want to create a simple division program but it cannot divide negative numbers as it may introduce some bugs. So have to create a custom exception class that will produce an exception in runtime whenever the user enters a negative integer either in Numerator or denominator. We will do all this step by step.
3.2.1 Create a Custom base exception class that will inherit
class CustomBaseException(Exception): pass
3.2.2 Creating our main Custom exception class
Let us create a new class named
NegativeDivisionErrorwhich will inherit the
CustomBaseException class and will contain the main code for our scenario. First, we have to define the __init__() method that will take the 2 arguments
*args, that will take all the arguments as a tuple that are passed when raising the exception of this class
class NegativeDivisionError(CustomBaseException): def __init__(self,*args): if args<0: self.res="NegativeDivisionError Exception: Numerator Cannot be Negative" elif args<0: self.res="NegativeDivisionError Exception: Denominator Cannot be Negative"
3.2.3 Defining __str__() method
Now we have defined __init__() method, its time to define __Str__() method that will define the print behaviour of our exception class. Basically, if we got any res then it will return it.
def __str__(self): if self.res: return self.res
3.2.4 Complete code
class CustomBaseException(Exception): pass class NegativeDivisionError(CustomBaseException): def __init__(self,*args): if args<0: self.res="NegativeDivisionError Exception: Numerator Cannot be Negative" elif args<0: self.res="NegativeDivisionError Exception: Denominator Cannot be Negative" def __str__(self): if self.res: return self.res try: a = int(input("Enter Numerator: ")) b = int(input("Enter Denominator: ")) if a<0 or b<0: raise NegativeDivisionError(a,b) c=a/b except NegativeDivisionError as nde: print(nde) else: print("Result of division is:",c)
So we have taken two integers from the user and if any of them is negative we will raise an exception passing both integers to our created
NegativeDivisionError class instance. If the condition evaluates to be
true then the exception will print as defined inside
except block else we will print the output of the division using
Let us run the code on different inputs.
Enter Numerator: 5 Enter Denominator: -3 NegativeDivisionError Exception: Denominator Cannot be Negative
Enter Numerator: -9 Enter Denominator: 3 NegativeDivisionError Exception: Numerator Cannot be Negative
Enter Numerator: -7 Enter Denominator: -3 NegativeDivisionError Exception: Numerator Cannot be Negative
Enter Numerator: 6 Enter Denominator: 2 Result of division is: 3.0
In this tutorial we see how we can create our own exception classes to handle cases as per the requirement, If you have any doubt, feel free to ask in the comment section.
Happy Learning 🙂