Skip to content

API Reference

Graham Wheeler edited this page Jun 27, 2023 · 7 revisions

Overview

API Description
breakpoint() Break on the following line, if a client is connected; no-op otherwise.
configure() Set debug properties that cannot be set in debug configuration.
connect() Connect the debug server to a DAP client that is waiting for incoming connections.
is_client_connected() Check whether a client is connected to this debug server.
debug_this_thread() Used to identify python threads created using native APIs.
listen() Set up the debug server to listen for incoming DAP client connections.
log_to() Turn on debug server logging and configure path to which logs are written.
trace_this_thread() Enable or disable tracing on a per-thread basis.
wait_for_client() Block running user code until a DAP client is connected.

API Usage with examples

Debugging a simple script

Consider the following script:

print('Hello World')

First, let's import debugpy and start the debug server.

import debugpy
debugpy.listen(5678)  # listen for incoming DAP client connections on 127.0.0.1:5678

print('Hello World')

The code above does that, but it will not block execution until a DAP client is attached - the script just continues running. If you run it, by the time you attach using your IDE of choice, it will probably already finish and exit - thus, if a breakpoint is set on print, it might not be hit. Let's add wait_for_client() to block your code from running until you can attach to it.

import debugpy
debugpy.listen(("localhost", 5678))  # listen for incoming DAP client connections
debugpy.wait_for_client()  # wait for a client to connect

print('Hello World')

API reference

List ordered by most frequently used to lest frequently used.

connect(address)

Tells the debug server to connect to a DAP client that is accepting connections on the specified address. In Visual Studio Code, this corresponds to a "request": "attach" debug configuration with "listen".

  • address : address must be either a (host, port) tuple, as defined by the standard socket module for the AF_INET address family, or a port number by itself. If only the port is specified, host defaults to "127.0.0.1".
Usage
debugpy.connect(5678)
debugpy.connect(('localhost', 5678))

listen(address, *, in_process_debug_adapter: bool = False)

Tells the debug server to listen for incoming DAP client connections on the specified network interface and port. In Visual Studio Code, this corresponds to a "request": "attach" debug configuration with "connect". Once the debug server is started in a process, it will handle incoming DAP client connections until that process terminates; but only one connection can be active at any given time.

  • address : address must be either a (host, port) tuple, as defined by the standard socket module for the AF_INET address family, or a port number by itself. If only the port is specified, host defaults to "127.0.0.1". If port is set to 0, an unused ephemeral port is picked instead.

  • in_process_debug_adapter: by default a separate python process is spawned and used to communicate with the client as the debug adapter. By setting the value of in_process_debug_adapter to True a new Python process is not spawned. Note: the con of setting in_process_debug_adapter to True is that subprocesses won't be automatically debugged.

Returns a (host, port) tuple indicating the actual interface and port on which the debug server is listening. The return value is typically used when the function was called with port set to 0.

Usage
debugpy.listen(5678)
debugpy.listen(('localhost', 5678))

# See how to secure this option if you are using it with remote.
debugpy.listen(('0.0.0.0', 5678))

# if you don't want to select the port yourself
_, port = debugpy.listen(0)
host, port = debugpy.listen(('localhost', 0))

wait_for_client()

Blocks execution of your code until a client connects to this debug server. If a client is already connected, the function returns immediately. While this function is waiting, it can be canceled by calling wait_for_client.cancel() from another thread.

Usage
debugpy.wait_for_client()

To cancel, you will have to invoke wait_for_client.cancel() from another thread. cancel() can only be called after wait_for_client() is called at least once.

debugpy.wait_for_client.cancel()

debug_this_thread()

Makes the debugger aware of the current thread, and start tracing it. Must be called on any background thread that is started by means other than the usual Python APIs (i.e. the threading module), in order for breakpoints to work on that thread.

Usage
debugpy.debug_this_thread()
Example
import debugpy

def foo(x):
    debugpy.debug_this_thread()
    print('set breakpoint here')
    return 0

from ctypes import CFUNCTYPE, c_void_p, c_size_t, c_uint32, windll

event = threading.Event()

thread_func_p = CFUNCTYPE(c_uint32, c_void_p)
thread_func = thread_func_p(foo)
assert windll.kernel32.CreateThread(c_void_p(0), c_size_t(0), thread_func, c_void_p(0), c_uint32(0), c_void_p(0))

event.wait()

breakpoint()

Returns immediately if no DAP client is connected to this debug server. If a client is connected, then it simulates a breakpoint on the next line. On Python 3.7 and above, this is the same as builtins.breakpoint().

Usage
debugpy.breakpoint()
print('debugger stops here')
Example
import debugpy

def foo():
    debugpy.breakpoint()
    print('here')        # Debugger stops here
    debugpy.breakpoint() # Debugger won't stop since there is no next line in this block

foo()

log_to(path)

Sets a directory to write detailed debugpy logs. Several log files are generated, one for every process involved in the debug session. All log filenames start with debugpy., and end with .log.

  • path : Path to the directory where the logs should be written. The directory must already exist.

Usage

debugpy.log_to("/tmp/logs")

trace_this_thread(should_trace)

Tells the debug adapter to enable or disable tracing on the current thread. When the thread is traced, the debug adapter can detect breakpoints being hit, but execution is slower, especially in functions that have any breakpoints set in them. Disabling tracing when breakpoints are not anticipated to be hit can improve performance. It can also be used to skip breakpoints on a particular thread.

Tracing is automatically disabled for all threads when there is no client connected to the debug adapter.

  • should_trace : True to enable tracing. False to disable tracing.
Usage
debugpy.trace_this_thread(True)
Example
import debugpy

def foo():
    debugpy.trace_this_thread(True)

    # Some performance intensive operation.

    debugpy.trace_this_thread(False)

foo()

configure()

Sets a debug property that must be known to the debug server before the client connects. Such properties can be used directly in "launch" configurations, because in that case the debuggee process after the configuration is passed. But for "attach" configurations, the process can run for a long time before it receives the debug configuration from an attaching client, and thus a different mechanism must be used to set the property values.

Currently, the only property like that is "subProcess".

This function must be called before calling connect() or listen().

Usage
debugpy.configure({"property": value, ...})
debugpy.configure(property=value, ...)
Example

If you don't want the debug server to automatically inject itself into subprocesses spawned by the process you're attaching to, specify it like so:

debugpy.configure(subProcess=False)
debugpy.listen(...)

This is the "attach" equivalent to the following "launch" debug configuration:

{
    "subProcess": false
}