MCS 275 Spring 2021
Emily Dumas
Course bulletins:
We're starting a short unit on debugging.
Today we'll talk about interpreting error messages, and basic methods to fix them.
Any difference between the expected and actual behavior of a program is an error or bug. Some bugs stop the program's execution. In other cases the program proceeds (but does the wrong thing).
The process of finding and fixing errors in computer programs is called debugging.
Today we mostly focus on debugging errors that cause a program to stop.
Functions can call other functions, so at any moment the Python interpreter may have a number of function calls in progress.
def f(x):
"""Return the square of `x`"""
return x*x
print("The square of 8 is",f(8))
e.g. in the program above, when line 3 runs, the function called on line 4 is in progress.
The function calls currently underway are stored on the call stack, a data structure maintained by the interpreter.
The top of the stack is the function actively running; the others are waiting on this one to finish.
Just below the top is the function that called the one currently running, and so forth.
The Python interpreter raises exceptions to signal unexpected conditions. Programs can also raise exceptions themselves.
Unless caught by a try...except
block, raising an exception ends the program.
When exiting due to an exception, Python prints a summary of what happened, called a traceback.
Tracebacks contain lots of useful information about what went wrong, including the call stack.
Determine where the code's meaning doesn't match the programmer's intentions.
Usually a change is needed near one of the lines in the traceback... but which one?
int("15").strip()
["a","b"]["foo"]
or trying to use indexing on a type that doesn't allow it
False[2]
int("space wasps")
["a","b"][15]
{"a": 260, "b":330}["autumn"]
from
)So far: Read-only debugging methods (no code changes to assist the process)
Reality: Debugging is hard. Tracebacks alone often don't give enough information.
Various debugging strategies can be used to help identify and fix problems.
One of the oldest debugging strategies is to add extra output to a program that shows important internal state up to the moment of an error.
E.g. print values of arguments and variables just before the line causing an exception.
Disadvantage: Generally need to remove all those scattered print()
calls when you're done debugging.
Print debugging is often criticized as the refuge of those who don't know any better.
We'll talk about another method next time, so you will know better!
But the simplicity and directness of simply printing more program state is often compelling.
Brian Kernighan (Unix co-creator) called print debugging the “most effective debugging tool” in 1979, and it remains popular more than 40 years later.