Create Custom Exceptions in Python

Create Custom Exceptions in Python

Rayven Esplanada Aug-10, 2021 Jun-03, 2021 Python Python Exception
  1. Create a Custom Exception Class in Python
  2. Execute Exception-Handling Using the try...except Block in Python

This tutorial will demonstrate you can create custom exception classes in Python. Here, we’ll show how you can properly perform exception handling, define custom exception classes, and override existing built-in exceptions.

Exceptions are a type of event that occurs whenever something within a program doesn’t go as intended or disrupts the flow of the intended use-case of the program. Without exception handling, the program will cease to execute entirely, and the exception would have to either be fixed or handled.

Create a Custom Exception Class in Python

Creating an Exception Class in Python is done the same way as a regular class. The main difference is you have to include the Python’s base Exception class to inform the compiler that the class you’re making is an exception class.

Let’s test this method out to create an exception class called DemoException and use the placeholder control flow keyword pass inside as a placeholder.

class DemoException(Exception):
    pass

Execute Exception-Raising Using the Keyword raise in Python

To test the DemoException class and see what it displays when it’s actually triggered, perform exception raising. Exception-raising is synonymous with exception-throwing in other programming languages.

Using the keyword raise, trigger an exception using the given exception class and outputs an exception message.

class DemoException(Exception):
    pass

raise DemoException

Output:

Traceback (most recent call last):
  File "/Users/demo/python/demo_exception.py", line 4, in <module>
    raise DemoException
__main__.DemoException

A standard exception will look like in the terminal if no custom exception message has been declared.

Declare a Custom Exception Message in Python

To declare a custom exception message for DemoException, override the __init__() method of the exception class and include the message that should be outputted for the exception in the parameters, along with the mandatory self-referential parameter self.

For example, let’s override the __init__() method and create a custom message for the DemoException class:

class DemoException(Exception):
    def __init__(self, message):
        super().__init__(message)

Take note that for the message to be integrated into your exception successfully, call the base Exception class, __init__() method, and include the message as an argument.

Let’s call the exception class again using the raise keyword, and now, passing a custom message with it:

class DemoException(Exception):
    def __init__(self, message):
        super().__init__(message)
        
message = "Exception Triggered! Something went wrong."
raise DemoException(message)

The output should look like this:

Traceback (most recent call last):
  File "/Users/demo/python/helloworld.py", line 6, in <module>
    raise DemoException(message)
__main__.DemoException: Exception Triggered! Something went wrong.

We’ve now successfully created and triggered an exception class with a custom error message.

For actual situations that may trigger an exception, how do we handle and raise these exceptions? You can solve this problem neatly by implementing exception-handling using the try...except block.

Execute Exception-Handling Using the try...except Block in Python

The try...except block is much like the try-catch block in other languages like Java.

The try...except block has 2 main blocks and 2 optional blocks:

  • try (required) - The main block responsible for encapsulating the code block where the exception might be triggered. The try block halts the whole process within it whenever an exception is triggered.
  • except (required) - The block program proceeds whenever a specified exception is triggered. This block typically contains a descriptive error message for the caller or just a simple print() statement. There may be more than one except block in a single try block, each one catching different exceptions.
  • else (optional) - This optional block is where the program will proceed if the try block did not trigger any exceptions.
  • finally (optional) - This optional block runs once everything from the previous 3 blocks has been performed regardless if an exception is triggered or not.

Let’s use the previous example using the DemoException class to try a simple try...except block.

First, wrap the raise keyword in a function and put it inside the try...except block.

The function that we’ll create for this example is a function that accepts a number and throws an exception if it sends 0. If it sends any other number, then the code will proceed as intended. Check the example below:

class DemoException(Exception):
    def __init__(self, message):
        super().__init__(message)
        

message = "Exception Triggered! Something went wrong."

def triggerException(num):
    if (num == 0):
        raise DemoException(message)
    else:
        print(num)


try:
    triggerException(0)
    print("Code has successfully been executed.")
except DemoException:
    print("Error: Number should not be 0.")

Since the triggerException() passed 0 as an argument, the code should trigger DemoException. Here we should expect the raise keyword message to be overridden with whatever is inside the except block as the output.

Notice that the print() line after the triggerException() function call was not outputted. It’s because the function raised an exception; therefore, it immediately halted all the processes within the try block and proceeded directly to the except block.

Output:

Error: Number should not be 0.

Now, let’s try passing a valid number like 20, for example.

try:
    triggerException(20)
    print("Code has successfully been executed.")
except DemoException:
    print("Error: Number should not be 0.")

Output:

20
Code has successfully been executed.

Let’s try chaining the except blocks and create another exception. Let’s call the new exception NumberFormatException, which triggers if the given input is not a number. For this exception class, let’s declare the message inside the class.

class NumberFormatException(Exception, value):
    message = f'{value} is not a number'
    def __init__(self):
        super().__init__(message)

Now, modify the code above to handle the new exception class NumberFormatException:

class DemoException(Exception):
    def __init__(self, message):
        super().__init__(message)
        
class NumberFormatException(Exception):
    def __init__(self, message, value):
        message = f'{value} is not a number'
        super().__init__(message)
        
message = "Exception occured."

def triggerException(num):
    if (not num.isdigit()):
        raise NumberFormatException(message, num)
    elif (num == 0):
        raise DemoException(message)
    else:
        print(num)

num = "sample string"
try:
    triggerException(num)
    print("Code has successfully been executed.")
except DemoException:
    print("Error: Number should not be 0.")
except NumberFormatException:
    print(num+" is not a number.")

In this code, the value of num that was passed to triggerException() is a string 'sample string' so the NumberFormatException should be triggered.

Output:

sample string is not a number.

In summary, creating custom exceptions in Python is as simple as creating a new class, but with the Exception class as an extra argument in the class definition. The raise keyword is used to trigger exceptions given the Exception Class. The try...except blocks are used to wrap one or more exceptions within a code block and modify what the code does when handling that exception and not just shutting down the program entirely.

Related Article - Python Exception

  • Open File Exception Handling in Python
  • Python Mock Raise Exception
  • Rethrow Exception in Python
  • Raise Exception in Python
  • Handle NameError Exception in Python
  • Python except Exception as e