Python Errors & Exception Handling Tutorial

In this tutorial we learn how to catch and handle errors with Python's built-in exception handlers, the try/except and try/finally blocks. We also cover how to raise error and warning exceptions.

What is an exception

When writing programs we will inevitably, and more often than not, encounter errors caused by not following proper syntax.

These errors are known as exceptions. The Python interpreter will raise an exception (stop the program and the report the error) when it encounters illegal operations.

Throughout the tutorial series we have seen various types of exceptions such as SyntaxError, KeyError, NameError, NotImplementedError etc. These exceptions help us track down, and repair the offending code.

List of built-in exceptions

The list of common Python exceptions, and their reasons, can be found at Python's official documentation .

How to handle exceptions

When exceptions are raised, they cause the current process to stop, and then pass the error to the calling process until the error is handled.

If the error is not handled, the application may crash.

How to catch exceptions with a try except block

We can use a try..except block to handle an exception in Python.

The operation that may raise an exception is written inside the try clause. The code that handles the exception is written inside the except clause.

Syntax: try..except
try:
    # code that may raise exception
except:
    # code to handle when error occured

Let’s consider a simple piece of illegal code that will raise a TypeError.

Example:
 print(1 + "Monty")

As we’ve already learned, we can’t add an integer and string together. It doesn’t make sense to the interpreter and it will raise a TypeError as a result.

We’ll add the statement to the try clause, and a custom error message to the except clause.

Example:
try:
    # erroring code
    print(1 + "Monty")
except:
    # error handling code
    print("Oops, can't int + string, it's illegal")

The example above is not very practical but demonstrates how to handle an exception.

How to catch specific exception types

We can evaluate code for specific error types and write handlers for each. A try..except block may have any number of except clauses to deal with different exceptions.

Syntax:
try:
    # code that may raise exception
except error_type:
    # code that handles error_type errors
except:
    # catch-all other exceptions
Example:
try:
    print(1 + "Monty")
except TypeError:
    print("Oops, can't int + string, it's illegal")
except:
    print("Oops, an error occurred")

We can combine error types in a single except clause with a tuple . To do this, we simply write comma separated error types inside parentheses.

Syntax:
try:
    # code that may raise exception
except (error_type_1, error_type_2, ...):
    # code that handles multiple error_type errors
Example:
try:
    print(1 + "Monty")
except (TypeError, NameError):
    print("Oops, found a TypeError or NameError")
except:
    print("Oops, an error occurred")

How to use a try finally block

A try except block may have an optional finally clause. The finally clause will always be executed and is generally used to release resources.

As an example let’s consider that we are manipulating a file on the system. Once we are done with the file, we need to do some cleanup, like saving and closing the file. These actions are done in the finally clause to guarantee their execution.

Syntax:
try:
    # do something
finally:
    # do this thing no matter what

In the same directory as the .py file you are currently working on, create a txt file called “test.txt” and then run the following example code.

Example:
try:
    f = open("test.txt", encoding = 'utf-8')
    # perform file ops
finally:
    if f.close:
        print("Cleanup complete.")

Because the close operation is in the finally clause, it will always close the file after any other operations.

How to explicitly raise an exception

We can forcefully raise exceptions or warnings when errors or warnings occur in our code. Optionally, we can pass a value to the exception to clarify why the exception has been raised.

How to raise an error

To raise an error, we use the raise keyword along with the error type. If we want custom text, we can specify that text as a value between parentheses.

Syntax:
raise NameError

# or

raise NameError("Reason")

As an example, let’s use a function that evaluates if a number is odd or even.

We’ll add a condition to check if the argument is an actual number. If not, we’ll explicitly raise a TypeError with raise .

Example:
def is_odd_num(num):
    if not isinstance(num, int):
        raise TypeError("Value must be an integer")
    elif num % 2 == 0:
        print(num, "is an even number")
    else:
        print(num, "is an odd number")

is_odd_num("Monty")

Because we invoke the function with a string argument, the interpreter will raise the TypeError with our custom text.

How to raise a warning

To raise a warning, we use the raise keyword with a warning type, or just the word Warning . If we want custom text, we can specify that text as a value between parentheses.

Syntax:
raise Warning

# or

raise Warning("Reason")

# or

raise warning_type
Example:
 raise Warning("You have been warned!")

Summary: Points to remember

  • When illegal operations occur, the interpreter will raise an exception, indicating an error in our code.
  • To avoid application crashes, we should catch and handle our exceptions.
  • We can catch exceptions with a try block, and handle them in an except block.
  • In a try..finally block, the finally clause will always be executed.
  • Errors and warnings are raised with the raise keyword.