MCS 275 Spring 2022
Emily Dumas
Course bulletins:
The Project 1 starter pack has a bug in environments.py
that makes the simulation behave slightly differently from the project description's claims.
It doesn't affect what you need to do, and I'm not making any changes.
The bug: If one bacterium asks to move to a point P
, and during the same time step, a new bacterium is created at P
, then both will succeed and P
will contain two bacteria.
Two lectures on debugging.
Today: 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. Might stop the program, might not.
The process of finding and fixing errors in computer programs is called debugging. It is difficult!
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, 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?
help()
if the error was in a call to a built-in function...and what they most often mean for debugging.
int("15").strip()
["a","b"]["foo"] # list index must be an integer
or trying to use indexing on wrong type
False[2] # bool doesn't allow indexing
or passing the wrong type to a function or operator
"asdf"**5 # cannot raise str to a power
len(5) # integers don't have a length
int("space wasps")
["a","b"][15]
{"a": 260, "b":330}["autumn"]
from
)os.getcwd()
.os.getcwd()
so you know where it looked, if you used a relative path or bare filename.So far: I mostly talked about read-only debugging methods (read and think).
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.
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.