Shiklo Tools
PDF40
Image20
Calculators & Converters25
Text & Writing13
Developer26
Video14
Audio14
Document14
Data & Spreadsheet12
Web & SEO9
OCR & Scanning5
Archive & File12
Security & Privacy23
Health & Medical29
QR & Barcode5

Python Errors and Debugging

Every programmer, beginner or expert, writes code with mistakes. The skill is not avoiding them but finding and fixing them quickly. Python helps a lot: when a program fails, it prints a traceback that says exactly where and why. This topic shows how to read tracebacks, what the most common errors mean, and how to hunt down bugs that do not produce an error at all.

Reading a traceback

def average(numbers):
    return sum(numbers) / len(numbers)

def report(name, marks):
    print(f"{name}: {average(marks):.1f}")

report("Asha", [90, 85])
report("Ravi", [])
Output
Asha: 87.5
Traceback (most recent call last):
  File "main.py", line 8, in <module>
    report("Ravi", [])
    ~~~~~~^^^^^^^^^^^^
  File "main.py", line 5, in report
    print(f"{name}: {average(marks):.1f}")
                     ~~~~~~~^^^^^^^
  File "main.py", line 2, in average
    return sum(numbers) / len(numbers)
           ~~~~~~~~~~~~~^~~~~~~~~~~~~~
ZeroDivisionError: division by zero

Read a traceback from the bottom up. The last line names the error and gives its message: dividing by zero. The lines above show the chain of calls that led there, the most recent last: line 2 in average was called from line 5 in report, which was called from line 8. The markers under each line point at the exact part that failed. The fix belongs where the empty list should be handled, for example by returning 0 when numbers is empty.

Common errors

ErrorUsual cause
SyntaxErrora missing colon, bracket or quote; Python cannot read the line
IndentationErrorthe spaces at the start of the lines do not match
NameErrora misspelt name, or a variable used before it gets a value
TypeErrorthe wrong kind of value, such as adding text and a number
ValueErrorthe right kind but a bad value, such as int("ten")
IndexErrora list index past the end of the list
KeyErrora dictionary key that does not exist
AttributeErrora method or attribute this kind of value does not have
ZeroDivisionErrordividing by zero

In our editor, each error also gets a short hint in plain words, and the line is marked in the code.

Bugs without errors

The hardest bugs give no error: the program runs but prints the wrong answer. The oldest technique still works best: print the values along the way and compare them with what you expect. f-strings with = show the expression too:

prices = [100, 250, 75]
total = 0
for p in prices:
    total = p             # the bug: should be total += p
    print(f"{p=} {total=}")
print("Total:", total)
Output
p=100 total=100
p=250 total=250
p=75 total=75
Total: 75

The printed values show at once that total is replaced instead of growing.

assert and small tests

assert condition, message stops the program with an AssertionError when the condition is false. Writing a few asserts for a function, with inputs whose answers you know, catches mistakes the moment you change the code:

def average(numbers):
    return sum(numbers) / len(numbers) if numbers else 0

assert average([90, 85]) == 87.5
assert average([]) == 0
assert average([7]) == 7
print("all tests passed")
Output
all tests passed

Practice exercises

  1. Run the first example, read the traceback from the bottom up, and fix average so that an empty list gives 0.
  2. Make each error from the table happen once on purpose, and read its message and hint.
  3. Find the bug in a loop that should count the even numbers in a list, using print.
  4. Write three asserts for a function that converts Celsius to Fahrenheit.