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 try
, except
, else
, finally
and 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 raise
keyword.
class CustomException(Exception):
pass
raise CustomException("Message related to exception")
Output:
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 magic methods
, __init__()
and __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 Exception
class
class CustomBaseException(Exception):
pass
3.2.2 Creating our main Custom exception class
Let us create a new class named NegativeDivisionError
which 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 self
and *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]<0:
self.res="NegativeDivisionError Exception: Numerator Cannot be Negative"
elif args[1]<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]<0:
self.res="NegativeDivisionError Exception: Numerator Cannot be Negative"
elif args[1]<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 else
block.
Let us run the code on different inputs.
Output 1:
Enter Numerator: 5
Enter Denominator: -3
NegativeDivisionError Exception: Denominator Cannot be Negative
Output 2:
Enter Numerator: -9
Enter Denominator: 3
NegativeDivisionError Exception: Numerator Cannot be Negative
Output 3:
Enter Numerator: -7
Enter Denominator: -3
NegativeDivisionError Exception: Numerator Cannot be Negative
Output 4:
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.
Resources:
Happy Learning 🙂