Python breakpoint() Function: Debug with pdb

Stuck on a value that looks wrong halfway through a function? Drop in the Python breakpoint() function: it pauses the script at that line and opens pdb, the built-in debugger, so you can print variables and step forward. No import is needed:

def order_total(prices, tax_rate):
    subtotal = sum(prices)
    breakpoint()          # execution pauses here
    ...

I ran the debugger sessions below in Command Prompt on Python 3.12.5 and typed the pdb commands for real; one comparison also uses Python 3.14.8.

In this tutorial, we’ll pause a script, use the core pdb commands, stop only on a bad row, switch breakpoints off with an environment variable, and plug in a custom hook.

How do you use breakpoint() in a Python script?

Put breakpoint() on the line where you want to look around, then run the file normally. Here I check a sales-tax total, print subtotal, run one line with n, print tax, and continue with c:

def order_total(prices, tax_rate):
    subtotal = sum(prices)
    breakpoint()
    tax = round(subtotal * tax_rate, 2)
    return round(subtotal + tax, 2)

print("Total:", order_total([19.99, 5.49, 12.00], 0.0825))

Output:

> c:\pyguides\bp_order.py(4)order_total()
-> tax = round(subtotal * tax_rate, 2)
(Pdb) p subtotal
37.48
(Pdb) n
> c:\pyguides\bp_order.py(5)order_total()
-> return round(subtotal + tax, 2)
(Pdb) p tax
3.09
(Pdb) c
Total: 40.57
Python breakpoint() opening a pdb session in Command Prompt, printing subtotal and tax before continuing
The (Pdb) prompt shows the paused line; p prints subtotal and tax, n runs one line, and c lets the script finish.

The -> line is the next line pdb will run. breakpoint() is one of the built-in functions in Python, so it works in any script from 3.7 on. The commands you’ll use most:

  • p expr / pp expr: print (or pretty-print) a value
  • n: run the next line; s: step into a call
  • l: list the code around the current line
  • c: continue; q: quit and stop the program

Where does Python breakpoint() stop in 3.13 and later?

The same file behaves a little differently on Python 3.14.8. Newer versions stop on the breakpoint() line, so tax doesn’t exist yet when I print it:

> c:\pyguides\bp_order.py(3)order_total()
-> breakpoint()
*** NameError: name 'tax' is not defined

So on 3.13+ press n once more before checking the next variable. That NameError is pdb reporting the error, not your script crashing; the types of errors in Python explains what each one means.

Use a conditional breakpoint() inside a loop

A breakpoint in a loop stops on every pass, which gets old fast. Wrap it in an if so it only fires on the row you care about, here a negative price:

cart = [("Notebook", 4.25), ("Backpack", 39.99), ("Pens", -2.50), ("Stapler", 11.75)]
total = 0
for item, price in cart:
    if price < 0:
        breakpoint()       # only stop on the bad row
    total += price
print(f"Cart total: ${total:.2f}")

Output:

> c:\pyguides\bp_cart.py(6)<module>()
-> total += price
(Pdb) p item, price
('Pens', -2.5)
(Pdb) p total
44.24
(Pdb) c
Cart total: $53.49
Python breakpoint() inside an if statement pausing a loop only on the Pens row with a negative price
pdb pauses once, on the Pens row with -2.5, and shows the running total before that row is added.

The cart has four rows but pdb only opened once. At the prompt you can read any name visible from that line, following Python variable scope rules.

Disable breakpoint() with PYTHONBREAKPOINT=0

Forgot a breakpoint() in code that runs unattended? Set the PYTHONBREAKPOINT variable to 0 and every call returns at once. In Command Prompt, quote the set so no trailing space sneaks in; more on that in environment variables in Python.

def apply_discount(price, code):
    rate = 0.15 if code == "FALL15" else 0
    breakpoint()
    return round(price * (1 - rate), 2)

print("Sale price:", apply_discount(89.99, "FALL15"))

Output:

Sale price: 76.49
Command Prompt running a Python script with PYTHONBREAKPOINT=0 so breakpoint() is skipped
With PYTHONBREAKPOINT set to 0 the script prints the sale price without opening pdb.

Custom breakpoint() hooks with PYTHONBREAKPOINT and sys.breakpointhook

PYTHONBREAKPOINT also accepts a module.function name. Python imports it and calls it instead of pdb, passing along any arguments you gave breakpoint(). This audit.py prints the caller’s locals:

import sys

def snapshot(*args, **kwargs):
    frame = sys._getframe(1)            # the function that called breakpoint()
    where = f"{frame.f_code.co_name}() line {frame.f_lineno}"
    print(f"[audit] {where}: {frame.f_locals}", kwargs or "")
def apply_discount(price, code):
    rate = 0.15 if code == "FALL15" else 0
    breakpoint(note="checking rate")
    return round(price * (1 - rate), 2)

print("Sale price:", apply_discount(89.99, "FALL15"))

Output:

[audit] apply_discount() line 3: {'price': 89.99, 'code': 'FALL15', 'rate': 0.15} {'note': 'checking rate'}
Sale price: 76.49
C:\pyguides\bp_audit.py:3: RuntimeWarning: Ignoring unimportable $PYTHONBREAKPOINT: "audit.missing"
  breakpoint(note="checking rate")
Sale price: 76.49
Custom PYTHONBREAKPOINT hook printing local variables, then a RuntimeWarning for an unimportable hook name
audit.snapshot prints the caller’s locals and the note argument; a misspelled hook only triggers a RuntimeWarning and the script keeps going.

Watch the arguments, though. Without a custom hook, pdb rejects them: TypeError: set_trace() got an unexpected keyword argument 'note'. To swap the hook from inside the program, assign sys.breakpointhook:

import sys

def log_hook(*args, **kwargs):
    caller = sys._getframe(1)
    print(f"skipped in {caller.f_code.co_name}(): {caller.f_locals}")

sys.breakpointhook = log_hook

def ship_cost(weight_lb):
    cost = 4.99 + 0.75 * weight_lb
    breakpoint()
    return round(cost, 2)

print("Shipping:", ship_cost(6))

Output:

skipped in ship_cost(): {'weight_lb': 6, 'cost': 9.49}
Shipping: 9.49

sys.__breakpointhook__ keeps the original pdb hook, so you can always put it back. For a clickable debugger with breakpoints in the gutter, compare editors in PyCharm vs VS Code for Python.

Handy reading once you’re debugging comfortably:

Frequently asked questions

What does breakpoint() do in Python?

It pauses the program and calls sys.breakpointhook(), which opens pdb by default, so you can inspect variables and step through code.

Is breakpoint() the same as pdb.set_trace()?

By default, yes. breakpoint() calls pdb.set_trace(), but it needs no import and can be redirected or disabled with PYTHONBREAKPOINT.

How do I disable all breakpoint() calls?

Set the environment variable PYTHONBREAKPOINT=0 before running the script. Every breakpoint() then returns immediately.

How do I exit the pdb debugger?

Type c to continue running, or q to quit, which stops the program.

Why does breakpoint() stop on a different line in Python 3.13?

Since 3.13, pdb stops on the breakpoint() line itself; older versions stop on the next line. Press n to move on.

Where is breakpoint() documented?

See breakpoint() in the Python docs.