Hyppää sisältöön

Ei vielä käännetty

Tätä sivua ei ole vielä käännetty suomeksi, joten se näytetään englanniksi. Auta kääntämään

breakpoint() Function Complexity

The breakpoint() function calls sys.breakpointhook(), passing its arguments straight through, and returns what the hook returns. Its own work is O(1); what a call costs is the hook's. The default hook reads the PYTHONBREAKPOINT environment variable on every call and either returns at once, calls the function the variable names, or enters pdb.

d is frames on the stack at the call and c is files in the linecache cache. A function named by PYTHONBREAKPOINT or installed as the hook costs whatever it does, added on top; importing its module the first time is a one-time cost the bounds leave out.

Complexity Reference

breakpoint and sys.breakpointhook

Operation Time Space Notes
breakpoint(*args, **kws) O(1) plus the hook O(1) plus the hook Calls sys.breakpointhook(*args, **kws) and returns its result; raises the builtins.breakpoint audit event first
sys.breakpointhook = hook O(1) O(1) breakpoint() then calls hook, and PYTHONBREAKPOINT is not read
sys.__breakpointhook__ O(1) O(1) The default hook, kept so a replacement can be undone

The default hook

Operation Time Space Notes
PYTHONBREAKPOINT unset or empty O(c + d) O(c + d) Calls pdb.set_trace() and waits for a command; the pdb page prices it, including the Pdb it builds
PYTHONBREAKPOINT=0 O(1) O(1) Returns None without importing anything
PYTHONBREAKPOINT=module.function O(1) plus the function O(1) plus the function Imports module and returns function(*args, **kws); a name with no dot is a builtin, such as int
PYTHONBREAKPOINT naming a missing module or attribute O(1) O(1) Emits a RuntimeWarning and returns None

Replacing the Hook

Assigning sys.breakpointhook routes every breakpoint() call to the new function, arguments and return value included. PYTHONBREAKPOINT is no longer consulted, so a test can intercept breakpoints whatever the environment says.

import sys

calls = []

def record(*args, **kws):
    calls.append((args, kws))
    return 'recorded'

previous = sys.breakpointhook
sys.breakpointhook = record
try:
    result = breakpoint('here', depth=3)  # O(1) plus record()
finally:
    sys.breakpointhook = previous

assert result == 'recorded'
assert calls == [(('here',), {'depth': 3})]

Choosing a Hook With PYTHONBREAKPOINT

The default hook reads PYTHONBREAKPOINT each time it is called, so changing os.environ takes effect on the next breakpoint(). 0 makes every call an O(1) no-op that returns None.

import os

os.environ['PYTHONBREAKPOINT'] = '0'
assert breakpoint() is None  # O(1): no debugger, no import

Any other value names a callable by its dotted path. The module part is imported, and the callable gets breakpoint()'s arguments and supplies its return value.

import os

os.environ['PYTHONBREAKPOINT'] = 'json.dumps'
assert breakpoint([1, 2]) == '[1, 2]'  # O(1) plus json.dumps([1, 2])

os.environ['PYTHONBREAKPOINT'] = 'int'
assert breakpoint('42') == 42  # no dot: the builtin int

A module that does not exist, or one without that attribute, is not an error: the call warns and does nothing.

import os
import warnings

os.environ['PYTHONBREAKPOINT'] = 'no_such_module.hook'
with warnings.catch_warnings(record=True) as caught:
    warnings.simplefilter('always')
    assert breakpoint() is None  # O(1): warns, no debugger

assert caught[0].category is RuntimeWarning
assert 'no_such_module.hook' in str(caught[0].message)

python -E and python -I ignore PYTHONBREAKPOINT, as they do the other PYTHON* variables, so under either a breakpoint() left in the code enters pdb even when the variable is 0.

Entering pdb

With PYTHONBREAKPOINT unset, breakpoint() is pdb.set_trace() at the call site: entering costs O(c + d), and the stop waits for input. After continue the program runs under the debugger's trace hook, or untraced if no breakpoints are set; the pdb page prices both, and how they differ between the 'settrace' and 'monitoring' backends.

Performance Best Practices

✅ Do:

  • Set PYTHONBREAKPOINT=0 where a stray breakpoint() must not stop the program: each call becomes O(1) and imports nothing
  • Replace sys.breakpointhook to intercept breakpoints in tests, saving the previous hook to restore; sys.__breakpointhook__ is the default
  • continue with no breakpoints set when you are done, so the rest of the program runs untraced

❌ Avoid:

  • Relying on PYTHONBREAKPOINT=0 under python -E or -I, which ignore it
  • Passing positional arguments to breakpoint() while PYTHONBREAKPOINT is unset: pdb.set_trace() accepts none and raises TypeError

Version Notes

  • Python 3.14+: the default hook's pdb.set_trace() reuses the last Pdb whose set_trace() ran, and otherwise builds one on the 'monitoring' backend; earlier releases build a new Pdb on every call
  • pdb - what the default hook enters, and the cost of running between stops
  • sys - sys.breakpointhook() and sys.__breakpointhook__
  • bdb - the trace events a debugger receives, priced per event