Stop debugging Python with print
Even though breakpoint() has been available since Python 3.7, many developers still reach for print to debug. Maybe out of habit or fear. Here is a quick example to get you started.
Suppose you have a shopping cart and want to calculate the total, applying a discount. You might write something like this:
def calculate_total(items):
total = 0
for item in items:
breakpoint() # Execution will stop here
total += item["price"] * item["quantity"]
return total
When execution reaches that line, the program stops and gives you a (Pdb) prompt. From there you can:
- Inspect variables:
p item,p total - Step line by line:
n(next) - Step into functions:
s(step) - Continue to the next breakpoint:
c(continue) - Exit the debugger:
q(quit)
You can also run any valid Python expression, modify variables, call functions, and so on.
Three ways to run the script
Normal execution
To debug, run the script as usual. The program will stop at the first breakpoint() and open the interactive (Pdb) console:
uv run demo.py
Ignore all breakpoints
The script runs straight through without pausing. Useful when you have finished debugging but have not removed the breakpoint() calls yet, or when running in a production environment.
PYTHONBREAKPOINT=0 uv run demo.py
Post-mortem mode
Useful for scripts that have no breakpoint() calls. The script runs normally and, if something crashes, drops you into the pdb console at the exact point of failure so you can inspect the state.
uv run python -m pdb -c continue demo.py
Commands
| Command | Action |
|---|---|
n (next) |
execute the current line without stepping into functions |
s (step) |
same, but steps into the called function |
c (continue) |
resume until the next breakpoint or the end |
l (list) |
show the code around the current line |
p expr |
print a variable or expression: p total |
pp expr |
same but pretty-printed, useful for dicts and lists |
w (where) |
show the call stack |
a (args) |
show the arguments of the current function |
r (return) |
execute until the current function returns |
q (quit) |
abort execution |
h (help) |
general help; h <command> for details on a specific one |
Final notes
The benefits of using breakpoint() and pdb are clear:
- It keeps the code clean, no
printstatements to remove afterwards. - You can inspect the program state at any point.
- You can modify variables and test changes on the fly.
- You can pause execution at any moment, not just when something crashes.
And it is a standard Python tool, no installation required.
Give it a try and see how it improves your workflow.
Happy debugging!
- Three ways to run the script
- Normal execution
- Ignore all breakpoints
- Post-mortem mode
- Commands
- Final notes
This work is under a Attribution-NonCommercial-NoDerivatives 4.0 International license.
Support me on Ko-fi
Comments
There are no comments yet.