Debugging#

1) Using a Python Traceback#

(Also called a slacktrace)

  1. blue box - Type of error

  2. green box - Error message

  3. red line - The specific line that caused the error

  4. yellow box - The files and functions/methods where the error occured

Key point:

Read a Python traceback from bottom to top

metadata = {
    'location': 'Nairobi', 
    'quality_flag': 5
    'zenith': 60, 
    'clouds': True,
    'data_center': ['LPDAAC', 'ASDC'],
}
metadata['Zenith"] == '7'
rotated_zenith = metadata['zenith'] + 90
print(rotated_zenith)
  Cell In[1], line 8
    metadata['Zenith"] == '7'
                            ^
SyntaxError: unterminated string literal (detected at line 8)

Indentify the parts of the slacktrace in the error message above.

Python Error Messages#

Python error messages are shown at the bottom of a Traceback. This is the first thing you often read in the traceback.

IndexError#

An IndexError occurs when you try to access a value using an index and that index does not exist in the object.

pollutants = ['co', 'co2', 'no2', 'o3']
pollutants[50]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-11-f05b51aac7dc> in <module>
      1 pollutants = ['co', 'co2', 'no2', 'o3']
----> 2 pollutants[50]

IndexError: list index out of range

KeyError#

A KeyError occurs when you are trying to access a named value of an object (a key) that does not exist. This is common in dictionaries and pandas DataFrames.

metadata = {
    'location': 'Nairobi', 
    'quality_flag': 5, 
    'zenith': 60, 
    'clouds': True,
    'data_center': ['LPDAAC', 'ASDC'],
}
metadata['start_date']
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-4-e954e279728c> in <module>
----> 1 metadata['start_date']

KeyError: 'start_date'

NameError#

A NameError occurs when you try to use a variable that doesn’t exist.

len(max_no2)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-10-8c7930fd591b> in <module>
----> 1 len(max_no2)

NameError: name 'max_no2' is not defined

SyntaxError#

A SyntaxError occurs when you have typed something that breaks the grammar rules of the core Python language. This could be extra parenthesis, mismatching quotes, backwards brackets, or a variety of other things.

len(pollutants
  File "<ipython-input-12-06668746c5e8>", line 1
    len(pollutants
                  ^
SyntaxError: unexpected EOF while parsing
metadata['zenith"]
  File "<ipython-input-13-feb0a3922969>", line 1
    metadata['zenith"]
                      ^
SyntaxError: EOL while scanning string literal

TypeError#

A TypeError is raised when you try to do something to an object, for example using a function, method, or operator, that the object can’t handle.

max_o3 = 95
len(max_o3)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-16-fbedace2e0dc> in <module>
      1 max_o3 = 95
----> 2 len(max_o3)

TypeError: object of type 'int' has no len()

AttributeError#

An AttributeError occurs when you try to get information from an object and the type of information you are looking for doesn’t exist on that type of object.

pollutants = ['co', 'co2', 'no2', 'o3']
pollutants.keys()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-25-4c211af94241> in <module>
      1 pollutants = ['co', 'co2', 'no2', 'o3']
----> 2 pollutants.keys()

AttributeError: 'list' object has no attribute 'keys'

ValueError#

A ValueError is raised when a function/method gets an input value that has the right type but the value is not appropriate. It is a very broad reaching error so it sometimes isn’t obvious what the problem is if you get a ValueError.

float('8')  # This is fine
float('pineapples')  # This isn't
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-48-37db5a3fe5f5> in <module>
      1 float('8')  # This is fine
----> 2 float('pineapples')  # This isn't

ValueError: could not convert string to float: 'pineapples'

Sometimes it’s mixed#

At times the error message you get won’t be the most helpful thing to lead to you to the solution. Keep this in mind - while the error message is a very useful place to start your debugging be open to considering additional avenues of error.

# Sometimes error messages are more cryptic
metadata['data_center'['LPDAAC']]
<>:2: SyntaxWarning: str indices must be integers or slices, not str; perhaps you missed a comma?
<>:2: SyntaxWarning: str indices must be integers or slices, not str; perhaps you missed a comma?
<ipython-input-24-22f4cb02bbce>:2: SyntaxWarning: str indices must be integers or slices, not str; perhaps you missed a comma?
  metadata['data_center'['LPDAAC']]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-24-22f4cb02bbce> in <module>
      1 # Sometimes error messages are more cryptic
----> 2 metadata['data_center'['LPDAAC']]

TypeError: string indices must be integers

Libraries#

Additional libraries will have their own custom errors that you will learn as you use them. Read the error message type to become familiar with the terminology then move on to reading the error message.

import rasterio
rasterio.open('./my_favorite_file.tif')
---------------------------------------------------------------------------
CPLE_OpenFailedError                      Traceback (most recent call last)
rasterio\_base.pyx in rasterio._base.DatasetBase.__init__()

rasterio\_shim.pyx in rasterio._shim.open_dataset()

rasterio\_err.pyx in rasterio._err.exc_wrap_pointer()

CPLE_OpenFailedError: ./my_favorite_file.tif: No such file or directory

During handling of the above exception, another exception occurred:

RasterioIOError                           Traceback (most recent call last)
<ipython-input-21-cce27133433b> in <module>
----> 1 rasterio.open('./my_favorite_file.tif')

~\.conda\envs\lessons\lib\site-packages\rasterio\env.py in wrapper(*args, **kwds)
    433 
    434         with env_ctor(session=session):
--> 435             return f(*args, **kwds)
    436 
    437     return wrapper

~\.conda\envs\lessons\lib\site-packages\rasterio\__init__.py in open(fp, mode, driver, width, height, count, crs, transform, dtype, nodata, sharing, **kwargs)
    218         # None.
    219         if mode == 'r':
--> 220             s = DatasetReader(path, driver=driver, sharing=sharing, **kwargs)
    221         elif mode == "r+":
    222             s = get_writer_for_path(path, driver=driver)(

rasterio\_base.pyx in rasterio._base.DatasetBase.__init__()

RasterioIOError: ./my_favorite_file.tif: No such file or directory

An Example#

Take a few minutes to debug the following block of code. Keep note of what strategies you use to find and fix errors.

  • How do you know when something isn’t working?

  • How do you decide what to try?

# Goal: Set a new value of 7 to the zenith then print the `rotated_zenith` value
# The output value should be 97.
metadata = {
    'location': 'Nairobi', 
    'quality_flag': 5
    'zenith': 60, 
    'clouds': True,
    'data_center': ['LPDAAC', 'ASDC'],
}
metadata['Zenith"] == '7'
rotated_zenith = metadata['zenith'] + 90
print(rotated_zenith)
  File "<ipython-input-4-780111995053>", line 6
    'zenith': 60,
    ^
SyntaxError: invalid syntax

Example 2 (pandas)#

import pandas as pd
# Import example WAS data
was_2020_filepath = "./data/SARP 2020 final.xlsx"
was_2020 = pd.read_excel(was_2020_filepath, "INPUT", skipfooter=7)
was_2020['Box'] = was_2020['Box'].astype(str)

The goal of the following piece of code is to show all ~20 rows where CH4 was greater than 1 from box 37.

was_2020[(was_2020['Box'] == 37) & (was_2020['CH4 (ppmv height)'] > 1)]['i-Pentane (E/B)'].plot())
  File "<ipython-input-55-2c466c8d93fe>", line 1
    was_2020[(was_2020['Box'] == 37) & (was_2020['CH4 (ppmv height)'] > 1)]['i-Pentane (E/B)'].plot())
                                                                                                     ^
SyntaxError: unmatched ')'

3) Reading Documentation#

Remembering arguments (args) and keyword arguments (kwargs)#

pollutants = ['co', 'co2', 'no2', 'o3']
# 'ch4' is an argument
pollutants.append('ch4')
# reverse=False is a key word argument
pollutants.sort(reverse=False)
pollutants
['ch4', 'co', 'co2', 'no2', 'o3']

Example with rasters: matplotlib.plot.imshow#

documentation page

import matplotlib.pyplot as plt
matrix = np.array([[3, 5, 7], [0, np.nan, 10], [np.nan, 4, 4]])
print(matrix)
[[ 3.  5.  7.]
 [ 0. nan 10.]
 [nan  4.  4.]]
plt.imshow(matrix)
<matplotlib.image.AxesImage at 0x2a0e29dc610>
../../_images/02f210761da131f25522f399301a0e26236dbf1fc51ca7217ec09571bb5cffd3.png
plt.imshow(matrix, cmap='BuGn')
<matplotlib.image.AxesImage at 0x2a0e19bf100>
../../_images/a38e3ec46731a815ae758861ad956020674420a4e4e147e11100030273d0fe43.png

Example with pandas: .plot.scatter()#

documentation page

import pandas as pd
# Import example WAS data
was_2020_filepath = "./data/SARP 2020 final.xlsx"
was_2020 = pd.read_excel(was_2020_filepath, "INPUT", skipfooter=7)
was_2020.plot.scatter(x='i-Butane (E/B)', y='n-Butane (E/B)')
<AxesSubplot:xlabel='i-Butane (E/B)', ylabel='n-Butane (E/B)'>
../../_images/e3e0450a2973aedad760bc4445078a0aa371588ba22c7ec7ea236441919f0565.png