Skip to content
Case 04 · 15 minutes

breakpoint() and pdb

Stop the program in the middle, look around, and step forward one line at a time. A debugger turns guessing into watching.

The evidencepage 1: review 11 ... 10 reviews

Goal#

Pause a running program with breakpoint(), inspect variables, step through code, and find an off-by-one bug.

The scene of the crime#

shell
uv run python -m detective run 4
output
page 1: review 11 ... 10 reviews
page 2: review 21 ... 5 reviews
page 3: (empty) ... 0 reviews

Page 1 starts at review 11. The first ten reviews never show.

Stop the world#

Add one line at the top of page() in lab/cases/case04_pdb.py:

python
def page(items: list[str], number: int, size: int = 10) -> list[str]:
    """Page `number` of `items`, counting pages from 1."""
    breakpoint()
    start = number * size

Run the case again. The program stops and hands you a (Pdb) prompt. A real session:

output
-> breakpoint()
(Pdb) p number, size
(1, 10)
(Pdb) n
-> start = number * size
(Pdb) n
-> return items[start : start + size]
(Pdb) p start
10
(Pdb) p items[start]
'review 11'

Page 1, size 10, start 10. There is the bug, caught in the act.

The commands you need#

CommandWhat it does
p exprprint any expression
nnext line, stepping over function calls
sstep into the function call on this line
llist the code around where you are
wwhere am I: the call stack, like a traceback
ccontinue until the next breakpoint
qquit the program

Remove the breakpoint() line when you are done. Then fix the start index, remembering that pages count from 1 and lists count from 0.

Check it works#

shell
uv run python -m detective check 4
  • Page 1 starts at review 1, page 3 has reviews 21 to 25, and page 4 is empty.

Exercise#

Set a breakpoint that only fires when it matters: if number == 3: breakpoint(). Run the case and check that you only stop once. Conditional breakpoints save hours in long loops.

More to try

  • Debug without editing the code at all: uv run python -m pdb -m detective run 4, then b cases/case04_pdb.py:13 to set a breakpoint on line 13, and c to run until it.
  • Your editor has the same debugger with buttons. Find "Run and Debug" in VS Code and set a breakpoint by clicking beside a line number.

Case 04, at a glance

uv run python -m detective run 4
uv run python -m detective check 4
uv run python -m detective hint 4

Run it from lab/. When check says PASS on every line, the case is closed.