You are stepping through a loop that processes 50,000 records and the bug only shows on one of them. A plain breakpoint stops on every iteration, so you hammer continue hundreds of times before reaching the interesting one — or give up. A conditional breakpoint stops only when a predicate is true, dropping you into the prompt on the exact iteration where the invariant breaks.
Prerequisites
- Python 3.7+ for
breakpoint(); theb,tbreak, andconditioncommands work in everypdbversion. - Familiarity with entering the debugger and the basic command loop from interactive debugging with pdb and ipdb.
Solution
There are two ways to make pdb stop conditionally: a line breakpoint with an inline condition, and a guarded breakpoint() call in source. Start with the command form, which requires no source edits.
# orders.py
def process(orders):
total = 0
for i, qty in enumerate(orders):
total += qty # we suspect a negative qty corrupts the total
return total
if __name__ == "__main__":
process([5, 3, 8, -2, 9, 4])
$ python -m pdb orders.py
(Pdb) b orders.py:5, qty < 0 # break at line 5 ONLY when qty is negative
Breakpoint 1 at orders.py:5
(Pdb) c # run; pdb skips every iteration until the predicate holds
> orders.py(5)process()
-> total += qty
(Pdb) p i, qty # we land exactly on the bad iteration
(3, -2)
The condition is any expression valid in the target frame; pdb evaluates it on every hit and stops only when it is truthy. To attach a condition to an existing breakpoint, or change one, reference the breakpoint by its number:
(Pdb) b orders.py:5 # unconditional breakpoint, gets number 1
Breakpoint 1 at orders.py:5
(Pdb) condition 1 qty < 0 # retrofit the predicate onto breakpoint 1
(Pdb) condition 1 # omit the expression to clear it again
For a breakpoint you only ever want to hit once — the common case inside a hot loop — use tbreak. It fires a single time and removes itself, so there is no leftover breakpoint to disable afterward:
(Pdb) tbreak orders.py:5, qty < 0 # one-shot: auto-removed after the first hit
Breakpoint 2 at orders.py:5
(Pdb) c
> orders.py(5)process()
-> total += qty
(Pdb) c # continues to the end; breakpoint is already gone
When you would rather express the predicate in source — for example because the condition is expensive or spans multiple statements — guard a breakpoint() call with an if:
def process(orders):
total = 0
for i, qty in enumerate(orders):
if qty < 0: # only enter the debugger on the offending value
breakpoint()
total += qty
return total
You can also raise the hit count with ignore: ignore 1 100 tells pdb to skip the next 100 hits of breakpoint 1 before honouring it — useful when you know the bug is "around iteration 100" but cannot express it as a value predicate.
Why this works
pdb stores conditions on the breakpoint object and evaluates them inside the paused frame's namespace via eval, so any in-scope name or expression is fair game. Because evaluation happens on every hit, a condition is functionally identical to a guarded breakpoint() — the command form just keeps the predicate out of your source. tbreak is a normal breakpoint with a temporary=True flag that pdb clears on first fire, and ignore decrements a counter before the condition is even checked.
Edge cases and failure modes
- A condition that raises (e.g.
qty < 0whenqtyis sometimesNone) makes pdb treat the breakpoint as hit and stops anyway — guard withisinstancechecks inside the expression if the variable's type varies. - Conditions evaluate in the target frame, not where you typed them; a name that exists in your prompt frame but not the breakpoint's frame raises
NameErroron every hit. - Side-effecting conditions run on every hit — never put a mutation or a
printin a condition; usecommandsfor that instead. tbreakwith a condition still consumes its single life on the first time the condition is true, not the first time the line is reached.- Conditional breakpoints add per-hit overhead; on a million-iteration loop the eval cost is noticeable, so prefer a guarded
breakpoint()orignorecount when the predicate is hot.
Frequently Asked Questions
How do I make pdb break only when a variable has a specific value?
Set the breakpoint with a condition: b orders.py:42, qty < 0. pdb evaluates the expression in the target frame on every hit and only stops when it is truthy, so the prompt opens on the iteration where qty goes negative.
What is the difference between break and tbreak in pdb?break (b) sets a persistent breakpoint that stops every time the line is reached. tbreak sets a temporary breakpoint that is removed automatically the first time it fires, which is ideal for stopping once inside a hot loop.
Can I add a condition to a breakpoint I already set?
Yes. Use condition bpnumber expression to attach or change the condition on an existing breakpoint by its number, or condition bpnumber with no expression to clear it and make the breakpoint unconditional again.
← Back to Interactive Debugging with pdb and ipdb