Errors and Exceptions

# Source: http://swcarpentry.github.io/python-novice-inflammation/07-errors/

Every programmer encounters errors, both those who are just beginning, and those who have been programming for years. Encountering errors and exceptions can be very frustrating at times, and can make coding feel like a hopeless endeavour. However, understanding what the different types of errors are and when you are likely to encounter them can help a lot. Once you know why you get certain types of errors, they become much easier to fix.

Errors in Python have a very specific form, called a traceback. Let’s examine some:


In [ ]:
# This code has an intentional error. You can type it directly or
# use it for reference to understand the error message below.
def favorite_ice_cream():
    ice_creams = [
        "chocolate",
        "vanilla",
        "strawberry"
    ]
    print(ice_creams[3])

favorite_ice_cream()

In [2]:
# Syntax error
def some_function()
    msg = "hello, world!"
    print(msg)
     return msg


  File "<ipython-input-2-d521ed171f38>", line 2
    def some_function()
                       ^
SyntaxError: invalid syntax

In [4]:
# Indentation Error
def some_function():
    msg = "hello, world!"
    print(msg)
     return msg


  File "<ipython-input-4-e169556d667b>", line 4
    return msg
    ^
IndentationError: unexpected indent

In [6]:
# Tab Error
def some_function():
    msg = "hello, world!"
    print(msg)
	return msg


  File "<ipython-input-6-548f3884eed4>", line 5
    return msg
              ^
TabError: inconsistent use of tabs and spaces in indentation

In [7]:
# Not defined
for number in range(10):
    count = count + number
print("The count is:", count)


---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-7-231bf30afc8f> in <module>()
      1 # Not defined
      2 for number in range(10):
----> 3     count = count + number
      4 print("The count is:", count)

NameError: name 'count' is not defined

In [11]:
# File Error
file_handle = open('myfile.txt', 'r')


---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
<ipython-input-11-6ec8179818ed> in <module>()
      1 # File Error
----> 2 file_handle = open('myfile.txt', 'r')

FileNotFoundError: [Errno 2] No such file or directory: 'myfile.txt'

Excercise

Read the python code and the resulting traceback below, and answer the following questions:

  • How many levels does the traceback have?
  • What is the function name where the error occurred?
  • On which line number in this function did the error occurr?
  • What is the type of error?
  • What is the error message?

In [16]:
# This code has an intentional error. Do not type it directly;
# use it for reference to understand the error message below.
def print_message(day):
    messages = {
        "monday": "Hello, world!",
        "tuesday": "Today is tuesday!",
        "wednesday": "It is the middle of the week.",
        "thursday": "Today is Donnerstag in German!",
        "friday": "Last day of the week!",
        "saturday": "Hooray for the weekend!",
        "sunday": "Aw, the weekend is almost over."
    }
    print(messages[day])

def print_friday_message():
    print_message("Friday")

print_friday_message()


---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-16-02e2580fb52c> in <module>()
     16     print_message("Friday")
     17 
---> 18 print_friday_message()

<ipython-input-16-02e2580fb52c> in print_friday_message()
     14 
     15 def print_friday_message():
---> 16     print_message("Friday")
     17 
     18 print_friday_message()

<ipython-input-16-02e2580fb52c> in print_message(day)
     11         "sunday": "Aw, the weekend is almost over."
     12     }
---> 13     print(messages[day])
     14 
     15 def print_friday_message():

KeyError: 'Friday'

Excercise:

Fix the following code:


In [17]:
seasons = ['Spring', 'Summer', 'Fall', 'Winter']
print('My favorite season is ', seasons[4])


---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-17-3b9451ba5207> in <module>()
      1 seasons = ['Spring', 'Summer', 'Fall', 'Winter']
----> 2 print('My favorite season is ', seasons[4])

IndexError: list index out of range

Excercise:

Read the code below, and (without running it) try to identify what the errors are.

  • Run the code, and read the error message. Is it a SyntaxError or an IndentationError?
  • Fix the error.
  • Repeat, until you have fixed all the errors.
def another_function print("Syntax errors are annoying.") print("But at least python tells us about them!") print("So they are usually not too hard to fix.")

Excercise:

  1. Read the code below, and (without running it) try to identify what the errors are.
  2. Run the code, and read the error message. What type of NameError do you think this is? In other words, is it a string with no quotes, a misspelled variable, or a variable that should have been defined but was not?
  3. Fix the error.
  4. Repeat steps 2 and 3, until you have fixed all the errors.
for number in range(10): # use a if the number is a multiple of 3, otherwise use b if (Number % 3) == 0: message = message + a else: message = message + "b" print(message)

Assertions


In [18]:
numbers = [1.5, 2.3, 0.7, -0.001, 4.4]
total = 0.0
for n in numbers:
    # Data should only contain positive values
    total += n
print('total is:', total)


total is: 8.899000000000001

In [19]:
def normalize_rectangle(rect):
    '''Normalizes a rectangle so that it is at the origin and 1.0 units long on its longest axis.'''
    assert len(rect) == 4, 'Rectangles must contain 4 coordinates'
    x0, y0, x1, y1 = rect
    assert x0 < x1, 'Invalid X coordinates'
    assert y0 < y1, 'Invalid Y coordinates'

    dx = x1 - x0
    dy = y1 - y0
    if dx > dy:
        scaled = float(dx) / dy
        upper_x, upper_y = 1.0, scaled
    else:
        scaled = float(dx) / dy
        upper_x, upper_y = scaled, 1.0

    assert 0 < upper_x <= 1.0, 'Calculated upper X coordinate invalid'
    assert 0 < upper_y <= 1.0, 'Calculated upper Y coordinate invalid'

    return (0, 0, upper_x, upper_y)

Debugging

You are assisting a researcher with Python code that computes the Body Mass Index (BMI) of patients. The researcher is concerned because all patients seemingly have unusual and identical BMIs, despite having different physiques. BMI is calculated as weight in kilograms divided by the the square of height in metres.

Use the debugging principles in this exercise and locate problems with the code. What suggestions would you give the researcher for ensuring any later changes they make work correctly?


In [ ]:
patients = [[70, 1.8], [80, 1.9], [150, 1.7]]

def calculate_bmi(weight, height):
    return weight / (height ** 2)

for patient in patients:
    weight, height = patients[0]
    bmi = calculate_bmi(height, weight)
    print("Patient's BMI is: %f" % bmi)