pdb: Python's Built-in Debugger
pdb is Python’s interactive source debugger, distributed as a module in the standard library. It supports setting breakpoints, single-stepping at the source-line level, inspecting and modifying variables in any stack frame, and post-mortem analysis of an unhandled exception. The interface is line-oriented and runs in any terminal with no external dependencies.
When to use pdb
Use pdb when a problem can be reproduced locally and adding a print statement is not enough. Drop a breakpoint() call at the line of interest, run the program, and inspect state interactively. For a crash that has already happened, run the script with python -m pdb -c continue script.py to land in post-mortem at the offending frame. pdb pauses the entire process, so it is not appropriate for debugging long-running production services; reach for logging or a sampling profiler instead.
Invocation
The three common entry points are an in-source breakpoint, running a script under pdb, and post-mortem analysis.
breakpoint() # Added in Python 3.7. Calls sys.breakpointhook(), which defaults to pdb.set_trace().python -m pdb script.py # run a script under the debugger from the start
python -m pdb -c continue script.py # run normally; only break on uncaught exception
python -m pdb -m mypackage.cli # run a module under the debugger (added in 3.7)
python -m pdb -p PID # attach to a running process (added in 3.14)PYTHONBREAKPOINT=0 disables every breakpoint() call in the process, which is useful for production deployments that should never enter an interactive debugger. Setting it to a dotted path (PYTHONBREAKPOINT=IPython.terminal.debugger.set_trace) routes breakpoint() to a different debugger.
For programmatic post-mortem analysis, pdb.pm() enters the debugger on the most recent unhandled exception, and pdb.post_mortem(tb_or_exc) enters on a specific traceback or exception object (exception-object support added in Python 3.13).
Commands
Program flow
s(step): execute the next line, descending into any called functionn(next): execute the next line, stepping over callsunt(until)[lineno]: continue past the current line, or until the given liner(return): continue until the current frame returnsc(continue): resume execution until the next breakpoint or program endj lineno(jump): set the next line to execute, skipping or replaying linesq(quit): exit the debugger and abort the program
Stack navigation
w(where): print the stack trace, current frame at the bottomu(up)[count]: move toward callersd(down)[count]: move toward calleesa(args): print the current frame’s argumentsretval: print the return value of the most recently returned function
Breakpoints
b [filename:]lineno(break): set a breakpoint at a lineb function: break on entry to a functiontbreak: set a temporary breakpoint, cleared after first hitcl [bpnumber ...](clear): remove breakpointsdisable bpnumber/enable bpnumber: toggle without removingcondition bpnumber expr: only stop whenexprevaluates trueignore bpnumber count: skip the nextcounthitscommands [bpnumber]: define commands to run automatically when the breakpoint is hit
Inspection
p expr: evaluate and printpp expr: pretty-printwhatis expr: print the typesource expr: show the source of a class or function (added in 3.2)display [expr]: re-printexprafter every step (added in 3.2)undisplay [expr]: stop tracking adisplayl(list): show source around the current linell(longlist): show the full current function (added in 3.2)interact: drop into a Python REPL with the current frame’s locals (added in 3.2)
Aliases and raw Python
alias name command [%1 %2 ...]: define a textual alias for a command sequenceunalias name: remove an alias! statement: execute an arbitrary Python statement in the current frame’s namespace
Configuration
pdb reads ~/.pdbrc from the user’s home directory and ./.pdbrc from the current working directory at startup. Both files are executed line-by-line as if typed at the debugger prompt; empty lines and lines beginning with # are ignored. The home file is read first, and the cwd file overrides it where they collide. Since Python 3.11, .pdbrc is read with UTF-8 encoding (previously the system locale).
.pdbrc is not Python source. It accepts pdb commands such as alias, b, c, and display. There is no syntax for multi-line aliases; chain statements with ; if needed, and remember that any names assigned during an alias leak into the debuggee’s frame.
The two example aliases from the official documentation print instance variables:
# print instance vars (usage: pi classInst)
alias pi for k in %1.__dict__.keys(): print(f"%1.{k} = {%1.__dict__[k]}")
# print instance vars in self
alias ps pi selfSince Python 3.2, .pdbrc may contain commands that resume execution, such as continue or next; earlier versions silently ignored them.
Limitations
- Line-oriented interface with no built-in syntax highlighting or call-graph view.
- Pauses the entire process, so it is not suitable for production debugging of long-running services.
- No first-class remote debugging in the standard library; reach for
remote-pdb,web-pdb, ordebugpy(the engine VS Code’s Python extension uses) for that.
Learn More
- pdb — The Python Debugger (official docs)
- Built-in
breakpoint()function PYTHONBREAKPOINTenvironment variable- Python Debugging With Pdb (Real Python)