The report says zero
Your manager opens the weekly support report. The average wait says "error". Last week it worked.
You could stare at the code and guess. Or you could check one thing at a time until the bug has nowhere to hide. The second way works every time.
By the end of this lesson
Note
I can find a bug by checking one thing at a time.
Key words
| Word | What it means | Example |
|---|---|---|
| Bug | a mistake that makes code give the wrong result | |
| Debugging | finding and fixing a bug | |
| Traceback | the report Python prints when it stops with an error | |
| Print debugging | printing values to see what the code really does | print("total", total) |
| Halving | checking the middle to rule out half the code |
The cells students fill in are left blank in this preview.
Read the last line of the error first
When Python stops, it prints a traceback. It looks long, but read it from the bottom.
The last line says what went wrong. The line above it says where. Everything higher up shows the calls that led there.
Most of the time, those two lines are all you need.
Worked example: one traceback, read upwards
| Traceback line | What it tells you |
|---|---|
| ZeroDivisionError: division by zero | What: something was divided by 0 |
| return total / len(waits) | The exact line that failed |
| File "report.py", line 6, in average_wait | Which file, line and function |
| print(average_wait([])) | The call that started it: an empty list |
The cells students fill in are left blank in this preview.
Try it: make the error, then fix it
def average_wait(waits):
# Minutes each support ticket waited for a first reply.
total = 0
for wait in waits:
total = total + wait
return total / len(waits)
print(average_wait([12, 30, 18]))
print(average_wait([]))
# Press Run. Read the last line of the error first.
# Then change the function so an empty list returns 0.
Print a value to see the truth
Some bugs give no error at all. The code runs and gives a wrong number.
Then add a print inside the code to show the values as they change. Compare each printed value with what you expected. The first line that differs points at the bug.
Take the extra prints out once it is fixed.
Practise: hours worked
def hours_worked(shifts):
# Each shift is [start hour, end hour] on a 24-hour clock.
total = 0
for shift in shifts:
start = shift[0]
end = shift[1]
total = start - end
return total
week = [[9, 17], [9, 13], [12, 20]]
print("Hours this week:", hours_worked(week))
# The answer should be 20. Add this line inside the loop:
# print("start", start, "end", end, "total", total)
# Run it, read each line, and fix the two mistakes.
A common mistake
Warning
Many people change several lines at once and hope one of them fixes it. Then they cannot tell which change mattered, and they may add new bugs. Change one thing, run it, and look again.
Halve the problem
In a long piece of code, check the value in the middle. If it is already wrong, the bug is in the first half. If it is right, the bug is in the second half.
Then check the middle of that half. Each check rules out half of what is left.
Worked example: halving 40 lines
| Check | Lines still suspect | Value at the middle | Bug is in |
|---|---|---|---|
| 1 | 1 to 40 | Right at line 20 | Lines 21 to 40 |
| 2 | 21 to 40 | Wrong at line 30 | Lines 21 to 30 |
| 3 | 21 to 30 | Right at line 25 | Lines 26 to 30 |
| 4 | 26 to 30 | Wrong at line 28 | Lines 26 to 28 |
The cells students fill in are left blank in this preview.