Python ships with the built-in pdb
module. You can use it without installing or importing anything:
Set breakpoints
file.py
# python < 3.7
import pdb
pdb.set_trace()
# python 3.7+
breakpoint()
Run your app/file (in your terminal)
Run file + stop at first breakpoint()
:
$ python file.py
Run file and stop at first line (with or without breakpoints):
$ python -m pdb file.py
Run file but ignore all breakpoints:
$ PYTHONBREAKPOINT=0 python file.py
You will see the pdb
prompt:
$ python file.py
> /project/file.py(line number)<module>()
-> print(f'path = {filename}')
(Pdb)
- The line starting with
>
tells you what file, line number and scope (module or function name) you’re currently in - The line starting with
->
is where execution is paused has not been run yet - The line starting with
(Pdb)
is thepdb
prompt waiting for a command - Output starts with
--Call--
when you’ve just stepped into a function - Output starts with
--Return--
when a value is about to be returned
(Pdb)
commands
General
<cr>
— repeat last command!<expr>
— execute python commandh
— help menuh <command>
— help for a commandrun
/restart
— restart debuggerq
/<c-d>
— quit debugger
Navigate lines of code
- “Step over”
n
— “next”: continue until next logically executed line (without entering function calls) or until current function’s return statement- useful for following every iteration of a loop
unt
— “until”: continue until line ≥ current line in current file (without entering function calls) or until current function’s return statement- like
n
but based only on moving farther down in current file - useful for not following every iteration of a loop
- like
unt #
— “until line”: continue until line ≥ # in current file (without entering functions) or until current function’s return statement- Like
n
+b
(or the idea ofc #
)
- Like
s
— “step into”: continue until next logically executed line (entering called functions) or until current function’s return statementr
— “return”: continue until current function’s return statementc
— “continue” until next breakpointj #
— “jump” to line number (e.g. to break out of a loop)
Navigate stack trace
w
— print stack trace with most recent frame at bottom and an arrow indicating the current frame (which determines the context of most commands)u
— move up the call stack- e.g. commands like
pp x
may output different values at different points in the stack trace - e.g. useful for spotting the function where a value changed unexpectedly
- e.g. commands like
d
— move down the call stacksource <expr>
— display source of expr
Inspect values
locals
— print local variablesa
— print args of current functionp <expr>
— print value of expr- e.g.
p var_1, var_2
- e.g.
pp <expr>
— pretty-print value of exprwhatis <expr>
— print type of exprl
— list 11 lines around current linell
— long-list all lines in current functionl #,#
— list lines in range
Watch values
display <expr>
— display value of expr whenever it changes- e.g. useful for watching a variable during a loop:
- e.g.
b #
(in loop body) +c
+display var
+c
+<cr>
, etc
display
— list all active display expressions (instead of just the first one)- useful after defining a watch list of expressions
- e.g.
b #
(in loop body) +c
+display var_1
+display var_2
+display var_3
+c
+display
+c
+display
, etc
undisplay
— clear all display expressionsundisplay <expr>
— stop displaying value of expr
Breakpoints
b
— list all breakpoints + their numbersb [filename:]lineno
— set bp at line in file (defaults to current file)- e.g.
b util:5
- e.g.
b 5
- e.g.
b [filename:]lineno, condition
— set bp if condition met (e.g. wrong input)- e.g.
b util:5, x == 'abc'
- e.g.
b 5, not x.startsWith(’a’)
- e.g.
b func_name[, condition]
— set bp at first line of function with optional condition- condition can only use function args and global variables available when function is entered (not local function variables); otherwise it will fail
- e.g.
b util.get_path
- e.g.
b get_path, not argument.startsWith(’/’)
cl # […]
— clear bp numbers (separate by spaces)cl filename:lineno
— clear all breakpoints at line in filecl
— clear all breakpoints (after confirming)disable #
— disable bp #enable #
— enable bp #ignore # count
— ignore bp # count timescondition # condition
— set/remove condition for bp number (remove if empty)
How to automatically enter debugger when an exception occurs?
Using pdb
to write new code
Useful for actually iterating slowly on new code:
- Write a few lines
- Then write a
breakpoint()
line - Run the file
- Inspect the values via the
Pdb
prompt (including creating temporary variables to save interesting values) to figure out what to write next - Write a few more lines, set a new breakpoint, and rerun with
pdb
- Repeat
I do this with console.log
when writing JavaScript, but this is a way to do the same with Python.
Research 📚
- pdb •
pdb
docs 📚 - Python Debugging With Pdb • Real Python 📖
- Python Debugger Cheat Sheet • Kapeli 📖
- How to use the Python Debugger using the breakpoint() • Patrick Loeber 📖
- Using breakpoint to debug in Python • Trey Hunner 📖
- An Introduction To Python Debugging with the PDB • TutorialEdge 📺
- Using pdb to Inspect Python Objects • Pybites 📺
- python debugger crash course: pdb / breakpoint (beginner - intermediate) anthony explains • Anthony Sottile 📺
- python: more advanced breakpoint() usage (intermediate) anthony explains • Anthony Sottile 📺
- Python: Debugger • Joe James 📺
- Python Quick Tip: Debugger and breakpoint() • Patrick Loeber 📺
- Python debugging with Python PDB - commands, post mortem and much more • Red Eyed Coder Club 📺
- Command-Line Python Debugging with pdb • NeuralNine 📺
- Start Python Debugging With pdb • Real Python 📺