A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://python.github.io/peps/pep-0553/ below:

PEP 553 – Built-in breakpoint()

PEP 553 – Built-in breakpoint()
Author:
Barry Warsaw <barry at python.org>
Status:
Final
Type:
Standards Track
Created:
05-Sep-2017
Python-Version:
3.7
Post-History:
05-Sep-2017, 07-Sep-2017, 13-Sep-2017
Resolution:
Python-Dev message
Table of Contents Abstract

This PEP proposes adding a new built-in function called breakpoint() which enters a Python debugger at the point of the call. Additionally, two new names are added to the sys module to make the choice of which debugger is entered configurable.

Rationale

Python has long had a great debugger in its standard library called pdb. Setting a break point is commonly written like this:

foo()
import pdb; pdb.set_trace()
bar()

Thus after executing foo() and before executing bar(), Python will enter the debugger. However this idiom has several disadvantages.

Python developers also have many other debuggers to choose from, but remembering how to invoke them can be problematic. For example, even when IDEs have user interface for setting breakpoints, it may still be more convenient to just edit the code. The APIs for entering the debugger programmatically are inconsistent, so it can be difficult to remember exactly what to type.

We can solve all these problems by providing a universal API for entering the debugger, as proposed in this PEP.

Proposal

The JavaScript language provides a debugger statement [js-debugger] which enters the debugger at the point where the statement appears.

This PEP proposes a new built-in function called breakpoint() which enters a Python debugger at the call site. Thus the example above would be written like so:

Further, this PEP proposes two new name bindings for the sys module, called sys.breakpointhook() and sys.__breakpointhook__. By default, sys.breakpointhook() implements the actual importing and entry into pdb.set_trace(), and it can be set to a different function to change the debugger that breakpoint() enters.

sys.__breakpointhook__ is initialized to the same function as sys.breakpointhook() so that you can always easily reset sys.breakpointhook() to the default value (e.g. by doing sys.breakpointhook = sys.__breakpointhook__). This is exactly the same as how the existing sys.displayhook() / sys.__displayhook__ and sys.excepthook() / sys.__excepthook__ work [hooks].

The signature of the built-in is breakpoint(*args, **kws). The positional and keyword arguments are passed straight through to sys.breakpointhook() and the signatures must match or a TypeError will be raised. The return from sys.breakpointhook() is passed back up to, and returned from breakpoint().

The rationale for this is based on the observation that the underlying debuggers may accept additional optional arguments. For example, IPython allows you to specify a string that gets printed when the break point is entered [ipython-embed]. As of Python 3.7, the pdb module also supports an optional header argument [pdb-header].

Environment variable

The default implementation of sys.breakpointhook() consults a new environment variable called PYTHONBREAKPOINT. This environment variable can have various values:

This environment variable allows external processes to control how breakpoints are handled. Some uses cases include:

PYTHONBREAKPOINT is re-interpreted every time sys.breakpointhook() is reached. This allows processes to change its value during the execution of a program and have breakpoint() respond to those changes. It is not considered a performance critical section since entering a debugger by definition stops execution. Thus, programs can do the following:

os.environ['PYTHONBREAKPOINT'] = 'foo.bar.baz'
breakpoint()    # Imports foo.bar and calls foo.bar.baz()

Overriding sys.breakpointhook defeats the default consultation of PYTHONBREAKPOINT. It is up to the overriding code to consult PYTHONBREAKPOINT if they want.

If access to the PYTHONBREAKPOINT callable fails in any way (e.g. the import fails, or the resulting module does not contain the callable), a RuntimeWarning is issued, and no breakpoint function is called.

Note that as with all other PYTHON* environment variables, PYTHONBREAKPOINT is ignored when the interpreter is started with -E. This means the default behavior will occur (i.e. pdb.set_trace() will run). There was some discussion about alternatively treating PYTHONBREAKPOINT=0 when -E as in effect, but the opinions were inconclusive, so it was decided that this wasn’t special enough for a special case.

Implementation

A pull request exists with the proposed implementation [impl].

While the actual implementation is in C, the Python pseudo-code for this feature looks roughly like the following:

# In builtins.
def breakpoint(*args, **kws):
    import sys
    missing = object()
    hook = getattr(sys, 'breakpointhook', missing)
    if hook is missing:
        raise RuntimeError('lost sys.breakpointhook')
    return hook(*args, **kws)

# In sys.
def breakpointhook(*args, **kws):
    import importlib, os, warnings
    hookname = os.getenv('PYTHONBREAKPOINT')
    if hookname is None or len(hookname) == 0:
        hookname = 'pdb.set_trace'
    elif hookname == '0':
        return None
    modname, dot, funcname = hookname.rpartition('.')
    if dot == '':
        modname = 'builtins'
    try:
        module = importlib.import_module(modname)
        hook = getattr(module, funcname)
    except:
        warnings.warn(
            'Ignoring unimportable $PYTHONBREAKPOINT: {}'.format(
                hookname),
            RuntimeWarning)
        return None
    return hook(*args, **kws)

__breakpointhook__ = breakpointhook
Rejected alternatives A new keyword

Originally, the author considered a new keyword, or an extension to an existing keyword such as break here. This is rejected on several fronts.

sys.breakpoint()

Why not sys.breakpoint()? Requiring an import to invoke the debugger is explicitly rejected because sys is not imported in every module. That just requires more typing and would lead to:

import sys; sys.breakpoint()

which inherits several of the problems this PEP aims to solve.

Version History References Copyright

This document has been placed in the public domain.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4