GEOG 489
Advanced Python Programming for GIS

1.7.1 Debugging

PrintPrint

As you may remember from GEOG 485, the simplest method of debugging is to embed print statements in your code to either determine how far your code is running through a loop or to print out the contents of a variable.

A more complicated and detailed method involves using the tools or features of your IDE to create watches for checking the contents of variables and breakpoints for stepping through your code. While we will introduce a range of IDEs at the end of the lesson and you will be investigating IDEs further and examining how their debugging tools work, we will provide a generic overview of the techniques here of setting watches, breakpoints and stepping through code. Don’t focus on the specifics of the interface as we do this. Instead, it is more important to understand the purpose of each of the different methods of debugging. While we could examine debugging using IDLE (or PythonWin as we did in GEOG 485) we’ve chosen to use a more representative IDE – Spyder as it more accurately demonstrates the features available in the majority of IDEs and you should also already have it installed from earlier.

We will start off by looking at Spyder’s debugging functions, which are similar to those of PythonWin from GEOG 485 and all other IDEs. You might remember back in GEOG 485 when we looked at debugging we examined setting up breakpoints, watches, and stepping through code. We’re going to revisit those concepts here briefly using Spyder; the same functionality will be available in all of the IDEs you’ll be investigating later but you might have to dig a little in the menus for it. There's more details in the Spyder help here.

For our debugging and profiling with Spyder, we’re going to use our raster multiprocessing example (the one that involved delineating streams from lidar data) from earlier. After starting Spyder and opening that file, click on the Debug menu and you will see a number of options.

Set the cursor to the line of code which filters our list of rasters :

new_rasters = filter_list(rasters,wildCardList) 

and set a breakpoint by choosing Set/Clear breakpoint from the Debug menu or pressing F12 or double-clicking alongside the line number of the code where you want a breakpoint (removing breakpoints uses the same methods as adding them).

Now run your code using the Debug item from the Debug menu, by pressing CTRL+F5, or using the debug button button. Your code will now start running and then pause prior to running the line of code at your breakpoint. 

One of the nice touches to Spyder is that it has a variable explorer pane, accessible from the View > Panes menu. This will show you a list of your variables, their type, size, and contents once they’re declared, and you can watch them change.

If you bring this pane up you will see two variables already in it, start_time and rasters, our list which has a size of 43 – that is 43 elements - so the code found 43 rasters in my case.

We can step to the next line of code using either Debug>Step, CTRL+F10, or the Step button step button. Notice that when you do this, an extra variable will appear in your list (new_rasters) and your next executable line of code will be highlighted in a pale grey band.

We can step through our code line by line to monitor its state as well as the contents of our variables to ensure that our code is doing what we expect it to. While we are doing this, we are looking for unexpected results in variables, loops that are not running correctly (either doing too many or too few iterations or not at all) and if/elif/else statements which are not being correctly evaluated.

While we can step through lines individually, there are also two more useful options in most IDEs which are "run current function until it returns" and "run to the next breakpoint." Spyder has these implemented using the buttons run until buttonand run to breakpoint button, respectively, and I suggest that you experiment with both to see how your functions are executed – particularly with the multiprocessing code. If you want to run between multiple breakpoints, you will need to add some more breakpoints to your code, otherwise, the code will run to the end.

Lastly, if you don’t want to step through all of the lines of code in a function, you can use the Step Return button step-return button , which will return you to the calling function.