25Jun
How to customize exceptions in python. Cover
How to customize exceptions in python

In this tutorial we will look at the purpose of exception, types of exceptions, why it is important to include exceptions in your python programs and where in a python program you can include exceptions.

In order to get practical understanding of how to use exceptions, we will build a python program to compute hash values of files based on md5 or sha256 algorithm.  We will implement custom  exceptions to deal with unexpected happenings such as empty input from users to prevent program from exiting abruptly.

NB: Exception and Error in this context are interchangeable.

Requirements:

You need to have python version 3.7 on your local host to run this program. You can check here to find out to install python version 3.7 .

What is an Exception?

Exception occurs when something that is expected to happen does not happen or something that is not expected happens.  There are certain exceptions or errors that we can handle such as type errors and those we can’t easily handle such as out of memory error.

For instance, let’s assume we have built a program in python which allows users to connect to soshace.com to download articles or tutorials as shown below:

import request
resp = request("www.soshace.com/how-to-build-a-python-program")
print("resp")

There is a possibility that the code above can end abruptly if there is no network connectivity or network latency is low.  In this case, we expected the user to connect and get the specified resource but because of connectivity problem, it can’t.

In another instance, the code below can return a type error if a user enters any other value apart from an integer because the index method for the list data type accept only integers.

users = ("Mike", "Nikita", "Kovavic", "Jokavic")   

names = list(users)

names["m"]

If you run this code via the python interpreter, it shows the following as type error because list indices do not support strings.

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list indices must be integers, not str

We can handle errors like those above using exceptions: whether in-built or user-defined.

Hierarchy of Exceptions

There are various classes of exception. All of these classes, in-built such as TypeError, IndexError and custom or user-defined, inherit directly from the BaseException class or from sub-classes of the BaseException class such as the Exception class.

However PSF recommends we inherit the Exception class instead of the Base Exception class. You can check here for a list of all exceptions in python.

The BaseException class is the super class of all classes or kinds of exceptions in python.

For instance, the code below technically shows how the InvalidAuth exception inherits from the Exception class.

 class InvalidAuth(Exception):  
    
    '' '' ''  Invalid authentication '' '' ''


    pass

NB: Inheritance in python allows a class to inherit attributes or behaviours otherwise known as methods from another class.

In this context, the InvalidAuth class becomes a subclass of Exception. So the Exception class is the super class of the InvalidAuth class.

You can check here for detailed information on inheritance, classes and super class in python 3.

Types of Exceptions:

In python there are two main types of exceptions: in-built and user-defined exceptions.

In-Built Exceptions:

Some instances of in-built exceptions in python are as follows:

KeyError:

This type of error or exception usually shows up or occurs when the specified key is not present in a data structure such as a dictionary.

The code below demonstrates how a program can terminate abruptly due to a key error if we decided to search for a non-existent key.

users["Mike"]= "Accra"

users["Nikita"]= "Petersburg"

users["James"]= "London"  

 

IndexError:

This type of error occurs when index accessed is out of range. This error shows up when a program make use of a list or tuple data structure to store data.

The code below demonstrates how a program can terminate abruptly due to an Index error.

country = ['Russia', 'Germany', 'England', 'Japan', 'Korea']

country[6]

 

NameError:

This type of error shows up if python interpreter tried to use a variable or a function but it has not been defined yet.   The code below shows how a name error occurs.

input(''create a directory:    '')  
os.mkdir(datastore)

 

AttributeError: 

Attribute error occurs when you try to access or contact an object’s attribute which does not yet exist.  The code below shows how attribute error occurs.

class   FileName:  


         def  __init__(self, file, path):   

            self.file = file  
            self.path = path   



f2.url

Apart from these errors or exceptions, there are other errors such as Timeout, TooManyRedirects, and ConnectionError. You can check here for additional in-built exceptions.

User-Defined Exceptions:

These type of exceptions are usually implemented by developers who need specific type of exception to handle errors.

Moreover, instead of also allowing in-built exception to output traceback when an exception is raised, we can customize it in our own way in this article. These type of exceptions inherit directly from the Exception class likewise in-built exceptions.

For instance, we can create an exception such as the one below to handle or catch error such as when a user tells the program to search for a file but that file is not available on the system.

class FileNotAvailable(Exception):  
   """ File is not available """

   pass    

Why it is important to include exceptions in your program:

The following shows why it is important to include exceptions in your python program to catch errors:

  1. It is unprofessional to deploy a program without a way to catch exceptions to production environment because it can dent a company’s reputation since the program can terminate abruptly or crash.
  2. The possibility of a company losing many customers due to the fact that it crashes often.
  3. Traceback printed by python can be a bit overwhelming.

Where in a python program can you include exceptions:

In this section, we will build a python tool to compute hash values of files. In addition, we will prevent the program from exiting abruptly by catching exceptions and customizing output to users.

On the terminal create a file using the following command:

touch cmd.py

Open the cmd.py file with vim editor and paste the following import statements:

import hashlib  

import shutil 

from os import platform

import sys 

Now save and close the cmd.py file using your file editor.

The import statements are as follows:

  • import hashlib:  This imports hashlib module otherwise known as hashing library. hashlib comes with one-way hashing algorithm such as SHA-256 family algorithms made up of SHA-1 and SHA-2.
  • import os:  This os module provides functions to interact with filesystem.
  • import shutil: This module provides functions we can apply on a collection of files.
  • import sys:  This module manipulates the python runtime environment. 

Now copy and paste the following code to the cmd.py file as shown below:

import hashlib
import sys
import os
import shutil


md5 = hashlib.md5()
sha256 = hashlib.sha256()




def make_dir():
  """ This function creates a directory within the program's directory """


  try:
      directory = input("create a directory:  ")
      os.mkdir(directory)
  except IOError:
     print("empty input not accepted. Create a directory")
  else:
     print("{} folder created successfully".format(directory)) 
     sys.exit()


def create_files():
  """ This function creates a file inside the program's directory """
  try:
      file = input("create files:  ")
      f = open(file, 'a') 

  except IOError:
      print("empty input is not accepted. Create a file")
  else:
      print("{} created successfully".format(file))
      f.close()
      sys.exit()


def  write_file():
  """ This function writes to a file inside the program's directory """

  file = input("choose file to write to: ")
  f = open(file, 'w', encoding='utf-8')
  text = input("write to file:    ")
  print("writing to {}".format(f))
  f.write(text)
  print("done!")

  f.close()
  sys.exit()




def  hash_files():

  """ This function compute hash values of selected files """

  files_to_hash = list()

  user_files = input("choose files to compute hash values: ")
  hash_algo = input("Select hashing algorithm(MD5 or SHA-1):   ")
  files_to_hash = user_files
  if hash_algo == 'md5':
      for file in files_to_hash:
           md5.update(file.encode('utf-8'))
           hash_values = md5.digest()
           print("{}: {} ".format(file, hash_values))

 else:

     for file in files_to_hash:
          sha256.update(file.encode('utf-8'))
          hash_values = sha256.digest()
          print("{} : {}".format(file, hash_values))



def display_menu():
 """ Displays functions to users on the terminal """
 print(""" 

       Methods Available:   

       1. Create files  
       2. Write to file
       3. Calculate files hash values 
       4. Create a directory 
       """)

def run():
 """ Displays menu and allows user to choose a specific method """


 while True:

   display_menu()
   method = input("select a method by a number(pick other number to quit program):  ")

   if method == "1":
       print("calling the function to create files....")
       create_files()

   elif method == "2":
        print("you are about to write to a file......")
        write_file()

   elif method == "3":
        print("calling the hashing function.....")
        hash_files()

   elif method == "4":
       print("calling the make directory function.......")
       make_dir()

 
   else:

        print("exiting program")
        sys.exit()


if __name__ == "__main__":
     run()


Then save and close the cmd.py file using your file editor.

The above code is made up of four functions respectively. These functions are described as follows:

  • create_files function:   This function allows a user to create files.
  • write_file function:  This function allows users to write to a file inside the program’s directory.  
  • hash_files function:  This function computes hash values of a file based on a user’s selected hashing algorithm.
  • make_dir function:  This function allows a user to create a directory inside the program’s root directory.

In addition,  we decided to catch errors and customize it in our own way during a user’s input such when creating a file or a directory.

On the terminal, execute the following command to run the program:

python3 cmd.py  

The program then prompts you to choose which function to run. You can choose to run any of the functions but initially you need to run the create_files and the write_file functions first.

Then afterwards, you can call the hash_files function to compute hash values for files created.

Conclusion:

Although in this article, we made use of the try except syntax to handle both expected and unexpected happenings, we can also make use of the if else syntax in python to handle exceptions by controlling the flow of the program with regards to user’s input.

So It is not always necessary to use the try except syntax to catch errors in the program. You can also deal with expected errors in a program using the if else syntax.

Email Support with Flask

This article is aimed at developers who are interested in implementing email support with Flask. In the following example, I will start with an overview of the Flask-Mail package followed by the code that explains to integrate email support with the Flask Web Application.

Leave a Reply