05 Debugging Primer
05 Feb 2019Code contains errors (also known as bugs — literally the first bug was a moth stuck in an electromechanical relay of the Mark II).
Bugs can be
- syntax and language errors (easy, relatively speaking) and errors that raise exceptions under certain conditions
- logic errors, corner cases, edge cases (hard)
Here we provide an introduction to the absolutely necessary business of identifying and fixing ("squashing") software bugs. Work through this page and then see More Resources at the end for more advanced material. Bug-hunting can be difficult and tedious but you have to do it — code that produces wrong results is useless.
General strategy
-
Be clear about what your code ought to do: what are the inputs, what are the outputs? What do you expect to get?
-
If you get an exception with a stack trace: look at the code that is referenced.
-
Output intermediate values (e.g.,
print()
calls). Compare what you get to what you expect. Run the program in your head to understand what values you should see. -
Make one change and re-run. Is the bug fixed? If not, repeat.
Helpful strategies
-
Have a terminal and an editor open, side by side, so that you can quickly run the modified code. (Don't forget to save changes before running the code…)
-
Prototype small code pieces interactively in
ipython
. -
Run programs inside
ipython
using the%run
magic function:
The advantage is that now you can examine variables interactively inside the interpreter.1
Activity: Fix as many bugs as possible!
Code for the examples below is in the PHY494-resources repository: Pull in the latest updates
then copy the code examples to your work directory for this lesson,
~/PHY494/05_debugging
,
and work there
Syntax and language
Bug 1
Print the numbers 0 to 9:
Bug 2
Print the squares of the numbers 0 to 9:
Bug 3
Print "error" for input 0:
Bug 4
Define the sinc-function :
Slicing and list building
A common problem is getting the indexing wrong, resulting in
IndexError
or subtle errors in the lists themselves. If faced with
slicing problems, try to build and slice lists interactively in
ipython
and then transfer the working slice recipe to your code. You
sometimes may want to create a simpler or shorter list for testing.
Bug 5
Show that my favorite season in Arizona is winter:
Bug 6
Create a list of values -10, -9.8, -9.6, …, -0.2, 0, 0.2, …, 10.
Edge cases
Edge cases occur at the boundaries of the allowed range of input; typically, you have to test them explicitly. (Corner cases occur when multiple edge cases come together.)
Bug 7
The sinc function is defined for all real numbers
but this implementation is incomplete.
- find values for which our function does not produce the correct result
- fix it
- BONUS: plot
sinc(x)
for values from -10 to 10 in steps of 0.2.
Logic errors
Logic errors tend to be the worst because your code runs and might even produce output that looks roughly correct even though it is wrong. You find logic errors by having a good understanding of what your code should produce for a given input and then trying different inputs and following the input through the code.
Bug 8
Create a list of squares of the first 10 natural numbers (0, 1, 2, …, 10) and print their sum 2:
Bug 9
Calculate the position of an object in free fall as a function of time and store time points (in 1-s intervals) and positions in two arrays (for plotting):3
More resources
- Software Carpentry's lesson on Errors and Exceptions
- Testing by Katy Huff
- Scipy lecture notes: Debugging by Gaƫl Varoquaux (advanced level)
Footnotes
-
Inside
ipython
you can also run the Python debugger using the%pdb
magic, but this is a more advanced topic. ↩ -
At least two errors are hidden here. ↩
-
Just in case: To stop a running Python program, press CONTROL and C at the same time (
control + c
). ↩