Python Exception Handling

This tutorial will give an introduction to what Python exceptions are, the most common types of exceptions, and how to handle raised exceptions with the try and catch clauses.

What is a Python Exception?

A Python exception is a construct used to signal an important event, usually an error, that occurs when executing a program. An exception may cause the program to stop if it is not properly "caught" (i.e. handled correctly). If you think that your program might raise an exception when executed, you will find it useful to use try/catch to handle them, which we'll see in the next section.

Handling Exceptions

In the example below, we prompt user to enter a number, and after execution the program gives out the value of the given number squared. The program will work as long as you enter a number as your input.

while True:  
    x = int(raw_input("Please enter a number: "))
    print("%s squared is %s" % (x, x**2))

When you enter a string, or any other character that is not a number, like "one", the program will raise a "Value Error" exception, as shown below:

$ python squared.py 
Please enter a number: 3  
3 squared is 9  
Please enter a number: 4  
4 squared is 16  
Please enter a number: five  
Traceback (most recent call last):  
  File "squared.py", line 4, in <module>
    x = int(raw_input("Please enter a number: "))
ValueError: invalid literal for int() with base 10: 'five'  

This is where handling exceptions comes in. You need to know how to properly handle exceptions, especially in production environments, because if they are not handled your program won't know what to do and will crash.

Let's see how we can handle the above error. This is done by surrounding the program that you think could raise an exception with a try keyword and matching it with a following except keyword to execute in case an exception is raised.

Let's rewrite the same program, and this time take care of any exceptions that may arise.

while True:  
    try:
        x = int(raw_input("Please enter a number: "))
        print("%s squared is %s" % (x, x**2))
    except ValueError:
        print("Please enter a valid number!")

As you can see from the above program, the code inside the try statement is executed first. If no error occurs, the rest of the code is executed and the except statement is skipped.

In the event that an exception is raised (like when entering a string instead of a number), the program executes the except statement that matches its try statement, followed the rest of the code outside of the try/except block, if any.

See what happens when we run our code with the try/except statements:

$ python safe_squared.py 
Please enter a number: 3  
3 squared is 9  
Please enter a number: 4  
4 squared is 16  
Please enter a number: five  
Please enter a valid number!  
Please enter a number: 5  
5 squared is 25  

Note: Please keep in mind that that an except clause will only handle exceptions from its corresponding try clause, even if there are multiple try/except clause handlers.

Types of Exceptions in Python

Python has several built-in exceptions. Let's take a glance at some of the most common exceptions so that you can get a perspective of what they are and how to use them.

KeyError Exception

This is an error that occurs when using a dictionary and you try to retrieve a key that is not present in the dictionary.

The following is a Django view used to authenticate users and it expects to receive a dictionary containing the keys "username" and "password". If any of the keys is not passed in the data, the program will raise a Key Error exception.

def authenticate_user(request):  
    try:
        email = request.data['username']
        password = request.data['password']

        user = authenticate(email=email, password=password)

        if user and user.is_active:
            return Response(user_details,status=HTTP_200_OK)
        else:
            res = {'error': 'can not authenticate with the given credentials'}
            return Response(res, status=status.HTTP_400_BAD_REQUEST)
    except KeyError:
        res = {'error': 'please provide a username and a password'}

By using try/except to catch the exception, our user will see the error instead of crashing our server.

IndentationError Exception

This kind of exception is raised when your code is not properly indented. Instead of using curly braces for specifying scope, Python uses indentation, so it is important to get the indentation correct, which is the purpose of this exception.

Let's write a function that checks if a number is even:

def is_even(number):  
    if number % 2 == 0:
    print(" %s is an even number" % (number))
    else:
    print("%s is an odd number" % (number))

print(is_even(1))  
print(is_even(2))  

The function will result in an Indentation Error on both lines 2 and 4 because it expects the code to be indented with 8 spaces, not 4.

If you execute the program, it will give the following output:

$ python is_even.py 
  File "is_even.py", line 3
    print(" %s is an even number" % (number))
        ^
IndentationError: expected an indented block  

SyntaxError Exception

This is one of the most common type of exceptions in Python. It occurs when there is an error in the syntax of your code.

Let's look at the example below:

def is_odd(n):  
    if n % 2 != 0:
        print(it's odd)
    else:
        print("not odd")

print(is_odd(7))  

The output of this code will result in an invalid syntax at line 3 because the string "it's odd" is not enclosed in quotes.

$ python is_odd.py 
  File "is_odd.py", line 3
    print(it's odd)
                  ^
SyntaxError: EOL while scanning string literal  

Keep in mind that there are many different types of syntax errors, and this is just one example.

TypeError Exception

This exception is raised when an operation or function is attempted that is invalid for the specified data type. In the example below, the function sum_of_numbers takes in 2 arguments and adds them together. When you attempt to call the function with 3 arguments, it raises a TypeError exception because it expects only 2arguments.

def sum_of_numbers(a, b):  
    return a + b

print(sum_of_numbers(1, 2, 7))  

Running this code yields the following result:

$ python sum_of_numbers.py 
Traceback (most recent call last):  
  File "sum_of_numbers.py", line 4, in <module>
    print(sum_of_numbers(1, 2, 7))
TypeError: sum_of_numbers() takes exactly 2 arguments (3 given)  

The try/catch, else, and finally Clauses

There are several other components of exception handling and that is the else and finally clauses.

We have already been able to use try and catch statements, which are used to catch errors. Let's now look at the else and finally statements as well.

The else Clause

The else clause is used to execute code when the program does not raise an exception. It is also better to use the else clause than adding additional code to the try clause. This is because it avoids unintentionally catching an exception that wasn't raised by the code being protected by the try/except statements.

Consider the example we used in the beginning of this tutorial, but instead we are going to execute the print statement inside the else statement.

while True:  
    try:
        x = int(raw_input("Please enter a number: "))
    except ValueError:
        print("Please enter a valid number!")
    else:
        print("%s squared is %s" % (x, x**2))

Running this code provides the same functionality as before, except that it isolates the error-prone int(raw_input(...)) code in the try statement, and the "safe" code in the else statement.

$ python else_squared.py 
Please enter a number: 3  
3 squared is 9  
Please enter a number: 4  
4 squared is 16  
Please enter a number: five  
Please enter a valid number!  
Please enter a number: 5  
5 squared is 25  

The finally Clause

This clause is meant to define clean-up actions that must be performed regardless of whether an exception was raised or not.

A finally clause must always be executed before leaving the try/catch statement, whether an exception has occurred or not. This is usually used to clean up, like to close an open file.

Let's include the finally clause in our example:

count = 0

while True:  
    try:
        x = int(raw_input("Please enter a number: "))
    except ValueError:
        print("Please enter a valid number!")
    else:
        print("%s squared is %s" % (x, x**2))
    finally:
        print("Ran %s time(s)" % count)

Running this code is similar to before, except that now we can see how many times our loop has run, regardless of whether an exception was raised or not:

$ python finally_squared.py 
Please enter a number: 3  
3 squared is 9  
Ran 1 time(s)  
Please enter a number: 4  
4 squared is 16  
Ran 2 time(s)  
Please enter a number: five  
Please enter a valid number!  
Ran 3 time(s)  
Please enter a number: 5  
5 squared is 25  
Ran 4 time(s)  

Conclusion

In this tutorial we briefly explained how to handle exceptions in Python using the try/catch statements, including some of the optional components, else and finally. I hope this tutorial has cleared out any confusion you had on Python Exceptions.

If you want to learn more, you can find more information in the Errors and Exceptions section of the Python documentation.

Author image
About Esther Vaati