Error handling in python: part 3

Thinking of where our program might go wrong is never ending. However, there are situations where you can predict the most common types of errors and plan for their occurrence. In this post we will learn how to test for specific error exceptions in Python.

Different types of errors

As part of this series of tutorials (1, 2), we have been working on a program called bmi_calc.py. This program takes the weight and height of the user and returns their body mass index (BMI). One of the lines in this program is:

weight = float(sys.argv[1])    # in kg

There are two errors that typically occur with this type of statement. First, the user may forgot to provide command-line arguments when using our program, which would mean sys.argv[1] is indexing a non-existent value. This is similar to having x = [1.2, 42.2, 24.3, 39.0] and then trying to access the value at x[6]. This is an IndexError in Python.

Second, the command-line argument provided by the user may not be a numerical value that can be converted to a floating point number. For example, float('60kg') and float('sixty') both return an error. This is called a ValueError in Python.

In the previous version of our program, we jumped to the except block of code regardless of what type of error occurred. This means that bmi_cal.py 60kg 1.7m would get the error This program needs two inputs, weight (kg) and height (m), which would be confusing given that two inputs were provided. Let’s fix this situation by testing for, and responding to, specific errors.

Testing for specific exceptions

Here is a new version of our program where we handle IndexError and ValueError in dedicated exception blocks:

import sys

try:
    weight = float(sys.argv[1])    # in kg
    height = float(sys.argv[2])    # in meters
except IndexError:
    print('This program needs two inputs, weight (kg) and height (m)')
    print('example: python bmi_calc.py 75 1.7')
    sys.exit(1)   # Abort program
except ValueError:
    print ('Weight (kg) and height (m) must be pure numbers.')
    sys.exit(1)
bmi = weight/height**2
print(bmi)

If the program is run without 2 command-line arguments, sys.argv[] will generate an IndexError and cause our program to jump to the code in the first exception block. However, if the program is run with non-numerical command-line arguments, float() will generate a ValueError and our program will jump to the code in the second exception block.

Error types.
In addition to the possibility of creating your own error types (see section 8.5 of the Python docs), Python has many built-in error types. Some of the most common are listed below:

  • IndexError: Indexing out of range (e.g., x=['me', 'you', 'them'], x[4]).
  • ValueError: Invalid conversion (e.g., float('two')).
  • NameError: Using an uninitialized variable (e.g., print (x) when x does not exist).
  • ZeroDivisionError: Dividing by zero (e.g., x = 42.0/0).
  • SyntaxError: Illegal use of Python key word or grammatical mistake (e.g., forr i in range(10)).
  • TypeError: Operation between two incompatible data types (e.g., 'a'/5).

Here is the output of the new version of our program:

$ python bmi_calc.py
This program needs two inputs, weight (kg) and height (m)
example: python bmi_calc.py 75 1.7

$ python bmi_calc.py 75kg 1.7
Weight (kg) and height (m) must be a pure number.

$ python bmi_calc.py 75 1.7
25.95155709342561

Conclusion

Testing for specific errors allows us to provide more appropriate error messages to the users of our program. In the next post, we will learn how to raise exceptions and gain complete control over how our program handles errors.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s