Debug Python Like a Pro with pdb: A Hands-On Guide

If your debugging workflow is “add a print(), rerun, delete the print(),” you are leaving time on the table. Python ships with pdb, a full interactive debugger, in the standard library. No install. No config. You can pause your program mid-execution, walk through it line by line, and inspect any variable.

This is a hands-on guide. We will debug a real (broken) script together. Every screenshot is from an actual terminal session.

1. Why pdb Beats print()

A print() tells you the value of one variable at one moment. pdb lets you:

  • Pause execution at any line (breakpoints).
  • Step forward one line, or step into a function call.
  • Print or evaluate any expression at that exact moment.
  • Walk the call stack to see how you got there.

2. The Minimal Way: breakpoint()

Python 3.7+ has a built-in breakpoint() function. Drop it wherever you want to pause:

def fetch(url):
    resp = requests.get(url, timeout=10)
    data = resp.json()
    breakpoint()          # execution pauses here
    return data['items']

result = fetch("https://api.example.com/items")

Run the script normally with python app.py. It freezes at breakpoint() and drops you into the (Pdb) prompt. Type p data to print data, n for next line, c to continue.

Editor showing a breakpoint set on the data = resp.json() line
Set a breakpoint in your editor, or just call breakpoint() in the code.

3. A Real Debugging Session

More often you want to start debugging from the command line without editing code. Use python -m pdb app.py. Here is a session where I set a breakpoint, continue to it, and inspect a variable:

Terminal showing a pdb session with break, continue, and print commands
A pdb session: set a breakpoint with b, run to it with c, inspect with p.

The key commands I use 90% of the time:

CommandShortWhat it does
nextnRun the current line, stop at the next line in this function
stepsStep into the function being called
continuecResume until the next breakpoint
breakbSet a breakpoint (b 42 for line 42)
printpEvaluate and print an expression
listlShow the source around the current line
wherewPrint the call stack
quitqExit the debugger

4. Post-Mortem Debugging (My Favorite Trick)

A script crashed with a traceback. Instead of rerunning and hoping to reproduce it, re-run it under pdb and it pauses exactly at the crash:

python -m pdb app.py

But the real magic is pdb.pm(). After a crash in an interactive session, call it to jump straight back into the stack at the failure point:

import pdb
pdb.pm()   # re-enter the traceback, inspect the dead frame

Here is what that looks like when a KeyError hides a real API problem:

Terminal showing a post-mortem pdb session revealing a 404 error payload
Post-mortem debugging: p prints the response and reveals the API returned an error, not a list.

In this case the bug was not “data['items'] is wrong” — the API had returned {"error": "not found", "status": 404}. A print() at the top would never have shown me that the response shape changed. Pausing at the crash did.

5. Save Time with .pdbrc

Create a ~/.pdbrc file to alias commands you type constantly. Mine:

alias ll list
alias pr pprint
alias cls !import os; os.system('clear')

Now ll lists source and pr obj pretty-prints. Small, but it adds up across a week of debugging.

6. pdb vs the VS Code Debugger

The VS Code debugger gives you clickable breakpoints and variable panes — great when you are in an editor. pdb is better when:

  • You are on a remote server with no GUI.
  • You are inside a docker exec shell or CI log.
  • The bug only reproduces in a production-like environment.

Learn both. They solve different situations.

7. Mistakes That Waste an Hour

  • Forgetting the import. Old Python needs import pdb; pdb.set_trace(). On 3.7+ just use breakpoint().
  • Stepping into library code. s dives into requests internals. Use n to stay in your function.
  • Editing code while paused. pdb does not reload your file. Exit, edit, rerun.
  • Leaving breakpoint() in production. It opens an interactive prompt that hangs servers. Remove it before deploying.

Frequently Asked Questions

Is pdb the same as the VS Code debugger?
Conceptually yes — both let you set breakpoints and inspect state. VS Code wraps a debugger (debugpy) in a GUI; pdb is the command-line original. Skills transfer between them.

Can I use pdb with pytest?
Yes: pytest --pdb drops into pdb on the first failure, and pytest --trace breaks at the start of each test. Indispensable for flaky tests.

What about richer debuggers like pudb or ipdb?
ipdb adds tab-completion and syntax highlighting on top of pdb and is my recommendation if you want a nicer prompt. pudb gives a full-screen curses UI. Both are pip install away.

That is enough pdb to debug almost anything. Next time a script misbehaves, resist the print() reflex and open (Pdb) instead.