pdb module
Overview
pdb is the Python debugger, part of the standard library. It lets you stop execution of a program and inspect the state of variables, evaluate expressions, and step through code line by line. It is useful when you need to understand why a program is behaving unexpectedly or crashing.
pdb is invoked in three main ways:
# 1. Run from the command line
python -m pdb script.py
# 2. Insert into your source code
import pdb; pdb.set_trace()
# 3. Use breakpoint() (Python 3.7+)
breakpoint()
Invoking the Debugger
From the command line
Running python -m pdb script.py starts the debugger before the first line of the script executes. The (Pdb) prompt appears immediately:
python -m pdb my_script.py
# > <string>(1)<module>
# -> import my_module
# (Pdb)
You can also pass arguments to your script:
python -m pdb my_script.py arg1 arg2
Within a running script
Insert breakpoint() anywhere in your code to pause execution at that point. This is the cleanest approach and respects the PYTHONBREAKPOINT environment variable.
def divide(a, b):
result = a / b
return result
def main():
x = 10
y = 0
breakpoint() # execution stops here
print(divide(x, y)
main()
Disabling breakpoint entirely
Set the PYTHONBREAKPOINT environment variable to 0 to disable all breakpoint() calls without removing them from the code:
PYTHONBREAKPOINT=0 python my_script.py
Conditional breakpoints
Append a condition to the break command to only pause when the condition is true:
# Inside pdb:
(Pdb) break 15, count > 3
In the source, use pdb.set_trace() with a condition:
import pdb
for i in range(100):
if i > 50:
pdb.set_trace() # only stops when i > 50
process(i)
PDB Commands
The debugger accepts single-character commands. Most can be shortened to one letter.
Navigation
| Command | Short | Description |
|---|---|---|
step | s | Execute the current line, stop inside any called function |
next | n | Execute the current line, do not descend into called functions |
continue | c | Resume execution until the next breakpoint or the program finishes |
return | r | Run until the current function returns |
until | unt | Continue until the line number is greater than the current |
# my_script.py
def faulty_func(x):
result = x * 2 # line 3
return result # line 4
faulty_func(5) # line 7
$ python -m pdb my_script.py
# (Pdb) break 3
# Breakpoint 1 at /path/my_script.py:3
# (Pdb) continue
# > .../my_script.py(3)faulty_func()
# -> result = x * 2
# (Pdb) step
# > .../my_script.py(4)faulty_func()
# -> return result
# (Pdb) next
# (Pdb) return
# The program finished.
Inspecting state
| Command | Short | Description |
|---|---|---|
print | p | Print the value of an expression |
pp | pp | Pretty-print the value |
list | l | Show source code around the current line |
longlist | ll | Show the full source of the current function |
where | w | Print the full stack trace |
up | u | Move up one stack frame |
down | d | Move down one stack frame |
args | a | Print the arguments of the current function |
source | so | Print the source code of an object |
# (Pdb) p my_var
# 42
# (Pdb) pp some_dict
# {'key': 'value',
# 'nested': {'a': 1}}
# (Pdb) where
# <string>(1)<module>()
# -> faulty_func(5)
# /path/my_script.py(7)<module>()
# (Pdb) args
# x = 5
# (Pdb) up
# > <string>(1)<module>()
# (Pdb) p x
# 5
Breakpoints
| Command | Short | Description |
|---|---|---|
break | b | Set a breakpoint at a line or function |
tbreak | tb | Set a temporary breakpoint (deleted after hit) |
disable | dis | Disable a breakpoint |
enable | ena | Re-enable a breakpoint |
clear | cl | Delete a breakpoint by number |
commands | Set commands to run automatically when a breakpoint is hit |
# (Pdb) break 10
# Breakpoint 1 at /path/my_script.py:10
# (Pdb) break my_func
# Breakpoint 2 at /path/my_script.py:5
# (Pdb) break
# Num Type Disp Enb Address What
# 1 breakpoint keep yes 0x... my_script.py:10
# 2 breakpoint keep yes 0x... my_script.py:5
# (Pdb) disable 1
# (Pdb) clear 2
# Deleted breakpoint 2
Managing execution
| Command | Short | Description |
|---|---|---|
quit | q | Exit the debugger and terminate the program |
exit | ex | Exit the debugger and terminate the program |
jump | j | Continue execution from a different line |
interrupt | “ | Press Enter to interrupt while the program is running |
Evaluating Python code
Prefix any command with ! to evaluate it as Python, or just type an expression at the (Pdb) prompt to print it:
# (Pdb) !my_var = 99
# (Pdb) p my_var
# 99
# (Pdb) !import os; print(os.getcwd())
# /home/user/project
Post-Mortem Debugging
When an unhandled exception causes a crash, pdb.post_mortem() drops you into the debugger with the traceback loaded:
import pdb
def risky():
return 1 / 0
try:
risky()
except ZeroDivisionError:
pdb.post_mortem()
Running this script produces:
$ python my_script.py
# > .../my_script.py(3)risky()
# -> return 1 / 0
# (Pdb)
Running Without Pdb
pdb.pm() enters post-mortem mode directly from the most recent exception:
import pdb
try:
int("not a number")
except ValueError:
pdb.pm()
Configuration
pdb reads a startup file at ~/.pdbrc if it exists. Commands in this file run automatically when pdb starts:
# ~/.pdbrc
# Enable pretty-printing by default
pp locals()
# Always show the full stack on entry
where
To skip the startup file, use python -m pdb -c "" script.py.
Command-Line Options
| Option | Description |
|---|---|
-m pdb | Run pdb as a module |
-c command | Execute a pdb command (can be used multiple times) |
-m pdb script.py --args arg1 | Pass arguments after -- |
# Run script with two pdb commands before first stop
python -m pdb -c "break 10" -c "continue" my_script.py
# Pass arguments to the script
python -m pdb my_script.py -- arg1 arg2
Common Mistakes
Using pdb.set_trace() in production code. Remove or guard pdb calls with an environment check:
import os
if os.environ.get("DEBUG"):
import pdb; pdb.set_trace()
Confusing step and next. step descends into functions; next runs them to completion without descending. Use next to skip over code you are confident about and step to dive into code you need to inspect.
Forgetting the program is paused. A long-running loop with a breakpoint inside it will appear frozen. Press c to continue to the next breakpoint or q to quit.
See Also
- /tutorials/intermediate-python/debugging-with-pdb/ — practical debugging sessions with pdb
- /reference/modules/traceback-module/ — extract and format tracebacks for logging
- /reference/modules/cprofile-module/ — profile Python code to find performance bottlenecks