In my previous article, I explained about Web scraping in Python. In this article, we’re going to take a look at exception handling in Python. Exceptions, also known as runtime errors are the errors that occur while the application is running.

There are two main types of errors in Python: static errors & runtime errors. Static errors are those errors that occur before the application is executed. Runtime errors are dynamic and occur based upon the conditions that affect the application during runtime. For instance the type of data, network speed, input or output signals, etc.

Technically we have to run the Python script in order to run the static errors too, however, to differentiate between static and runtime errors, we can say that all the syntax errors are static errors. On the other hand, exceptions involve errors other than syntax errors.

Two Types of Errors

Static Errors

Before we study runtime errors or exceptions, we need to understand static errors. A syntax error is a typical example of a static error. Look at the following code:

def div_nums:
    result = num1/num2
    print(result)

If you run the script above, you will see the following error:

File "<ipython-input-3-fd556aceaae0>", line 1
    def div_nums:
                ^
SyntaxError: invalid syntax

The error tells us that we have a syntax error in our code. You can correct the code above by simply adding a pair of parenthesis before the colon as shown below:

def div_nums():
    result = num1/num2
    print(result)

When you run the above script, you will not see any error. However, our code is still not correct because inside the div_nums() function, we are dividing the variable num1 by num2. The variables num1 and num2 have neither been initialized inside the div_nums() function nor have they been passed as parameters to the function. Still, you will not see any error when you run the above code. This is where the runtime errors or exceptions come to play.

Runtime Errors or Exceptions

Runtime errors or exceptions, as the name suggests, are the errors that occur while the application is running. Let’s see an example of an exception in Python:

def div_nums():
    result = num1/num2
    print(result)

Let’s now call the div_nums method:

div_nums()

When you run the above script, you’ll see the following exception:

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-5-97ce2b191d05> in <module>
----> 1 div_nums()

<ipython-input-4-5ce403df9e99> in div_nums()
      1 def div_nums():
----> 2     result = num1/num2
      3     print(result)

NameError: name 'num1' is not defined

The exception clearly says that we are trying to access a variable num1 which is not defined. This error was not generated when the body of the div_nums () function was parsed. Instead, it only occurred once the method was called, or in other words, the error occurred when the method was executed at runtime.

How to Handle Exceptions in Python

Exception handling in Python is straight forward. You simply have to wrap the piece of code that is likely to throw an exception inside a try block. The code that you want to execute in case of an exception is added to the except block that immediately follows the try block. Look at the following example:

def div_nums():
    try:
        result = num1/num2
        print(result)
    except Exception:
        print("An error has occured")

In the script above, when the exception occurs, the code that follows the except block executes. Let’s try calling the div_nums method again:

div_nums()

This time you will not see the jumbled up error message printed, rather you will see a clean error message printed by the except block i.e :

An error has occured

Handling All Types of Exceptions

Exceptions can be of multiple types. To have a better understanding of this concept, look at the following example:

def div_nums(num1, num2):
    result = num1/num2
    print(result1)

If you call the above method by passing 0 as the second argument to the div_nums() function, you will see that the script will thow ZeroDivisonError since a number cannot be divided by 0.

div_nums(10,0)

Output:

---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-18-4502269c738e> in <module>
----> 1 div_nums(10,0)

<ipython-input-17-fc076a179f65> in div_nums(num1, num2)
      1 def div_nums(num1, num2):
----> 2     result = num1/num2
      3     print(result1)

ZeroDivisionError: division by zero

Similarly, if you execute the following code, you will see the NameError exception since the variable result1 is not defined:

div_nums(10,5)

Output:

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-19-4fbca09cac8f> in <module>
----> 1 div_nums(10,5)

<ipython-input-17-fc076a179f65> in div_nums(num1, num2)
      1 def div_nums(num1, num2):
      2     result = num1/num2
----> 3     print(result1)

NameError: name 'result1' is not defined

To handle multiple exceptions, you can use an except block as follows:

def div_nums(num1, num2):
    try:
        result = num1/num2
        print(result1)
    except Exception:
        print("An error has occured")

Now no matter which exception occurs, the except block will always execute for any exception that arises and you will see the message An error has occured .

Handling Different Exception Types Individually

You can also include multiple types of except blocks for each try block. Each except block will be dedicated to handling a single exception type. In this way, you can execute different codes for different types of exceptions. Look at the following code for reference:

def div_nums(num1, num2):
    try:
        result = num1/num2
        print(result1)
    except ZeroDivisionError:
        print("You cannot divide a number by zero")
    except NameError:
        print("You have initialize a variable before using it")

In the script above, we have two except statements. The first except statement handles the ZeroDivisionError exception, while the second except statement handles the NameError exception. Each block prints a different message based on the type of exception that occurred. Let’s give it a try:

div_nums(10,0)

Output:

You cannot divide a number by zero

Similarly, when you try to use an uninitialized variable, you will see the following exception:

div_nums(10,5)

Output

You have initialized a variable before using it

Wrapping Up

That’s how you can handle exception in Python. Hopefully, you now have a clear understanding between static and runtime errors and how to handle runtime exceptions using try and except blocks in Python.

If you wish to learn more about Python, you can check out our collection of Python tutorials. Should you have any questions or doubts, feel free to leave a comment below