PythonDebugging (pdb)

Debugging (pdb)

When a program doesn't behave the way you expect, the fastest first move is usually adding a few print() calls to see what values look like at a given point. That works surprisingly often, but it has real limits: you have to guess in advance what to print, you have to edit the code and re-run it for every new guess, and you can't easily inspect state interactively. Python ships with a real interactive debugger, pdb, that lets you pause execution at an exact line and poke around the running program.

print() debugging vs. a real debugger

print() debugging

pdb (real debugger)

Setup

Edit source, add print calls

Drop in one line, or set a breakpoint

Iterating on a new question

Edit code again, re-run

Type an expression at the prompt, instantly

Inspecting arbitrary state

Only what you thought to print

Any variable, any expression, at that exact moment

Controlling execution

Not possible

Step line-by-line, step into calls, continue, etc.

Setting a breakpoint

Since Python 3.7, the easiest way to pause execution is the built-in breakpoint() function — no import required. It drops you into the pdb prompt at exactly that line.

Python
def total_price(items):
    subtotal = sum(item.price for item in items)
    breakpoint()  # execution pauses here
    tax = subtotal * 0.08
    return subtotal + tax

On older codebases, or if you want to be explicit about which debugger module is used, you'll still see the equivalent written out directly:

Python
import pdb

def total_price(items):
    subtotal = sum(item.price for item in items)
    pdb.set_trace()  # equivalent to breakpoint()
    tax = subtotal * 0.08
    return subtotal + tax

When execution reaches that line, the program stops and drops you into an interactive (Pdb) prompt right there, with full access to every local variable in scope.

> example.py(4)total_price()
-> tax = subtotal * 0.08
(Pdb) p subtotal
129.97
(Pdb) 
Essential pdb commands

Once you're at the (Pdb) prompt, a small set of one-letter commands covers almost everything you'll need.

Command

Meaning

n (next)

Run the next line, stepping over any function calls it makes.

s (step)

Run the next line, stepping into a function call if there is one.

c (continue)

Resume normal execution until the next breakpoint (or the end).

l (list)

Show the source code around the current line.

p expr (print)

Evaluate and print any expression — a variable, a function call, anything.

w (where)

Show the current call stack, i.e. how you got here.

b (break)

Set an additional breakpoint at a given line or function.

q (quit)

Abort debugging and stop the program entirely.

Python
(Pdb) l
  1     def total_price(items):
  2         subtotal = sum(item.price for item in items)
  3         breakpoint()
  4  ->     tax = subtotal * 0.08
  5         return subtotal + tax
(Pdb) p [item.price for item in items]
[49.99, 79.98]
(Pdb) n
(Pdb) p tax
10.3976
(Pdb) c
  • You can also run a whole script under the debugger from the start, without editing it: python -m pdb my_script.py.

  • Inside pdb, any line that isn’t a recognized command is evaluated as plain Python in the current scope — you can even reassign variables to test a fix live.

  • c continues until the next breakpoint or the program ends, so it’s safe to leave breakpoint() calls in a loop body and step through iterations one at a time.

Note
A very common mistake is leaving a `breakpoint()` call in code that gets deployed or committed — it will hang any process that isn't attached to an interactive terminal, waiting forever for input. Treat it the same way you'd treat a `print()` left in by mistake: remove it before committing.
In practice, most developers reach for a visual debugger
`pdb` is invaluable when you're working over SSH, inside a minimal container, or writing a quick throwaway script — anywhere a full IDE isn't available. But day to day, most Python developers debug visually: VS Code and PyCharm both have a built-in debugger where you click a line number to set a breakpoint and get a panel showing every variable, the call stack, and step buttons — all the same capabilities as `pdb`, without memorizing commands. It is worth learning both: the IDE debugger for daily work, and `pdb` for the moments when a GUI isn't an option.