Debugging: Tracebacks and a Real Fix
Bugs are normal. The skill is finding them calmly, and Python hands you a map: the traceback.
Read tracebacks bottom-up
When code crashes, Python prints a traceback. The last line names the error type and message; that is the most useful part. The lines above show the call chain that led there, with file names and line numbers.
Traceback (most recent call last):
File "app.py", line 12, in <module>
print(total / count)
ZeroDivisionError: division by zeroRead the bottom first: a ZeroDivisionError on the line total / count tells you count was 0. Now you know exactly where and why.
Bisect to localize
If you cannot see the cause, narrow it down. Drop a few print() calls (or asserts) to check values at the halfway point of the logic. Whichever half is wrong, bisect again. A handful of prints usually pins the bug fast:
def discount(price, percent):
print("price:", price, "percent:", percent) # is the input what I expect?
factor = percent / 100
print("factor:", factor) # is the math right?
return price - price * factorassert your assumptions
An assert states what you believe is true at a point in the code. If the belief is wrong, it fails loudly right there instead of corrupting results silently: assert count > 0, "count should never be zero here".
Here is a function with a subtle bug. It is meant to return the largest number in a list, but it returns the smallest. Read it, find the flaw in the comparison, and fix it.
# buggy
def find_max(numbers):
best = numbers[0]
for n in numbers:
if n < best: # wrong direction
best = n
return bestFix the buggy function. Define find_max(numbers) so it returns the largest number in a non-empty list. The starter has the wrong comparison operator. Make find_max([3, 9, 2, 7]) return 9. Bonus correctness: it should handle negative numbers too.
This lesson is locked
Lessons open one at a time. Finish the previous lesson to unlock this one.