PDB Attach
pdb-attach is a Python debugger extension that allows users to attach to already running Python processes. Unlike standard `pdb.set_trace()`, it facilitates debugging long-running or unresponsive applications by enabling remote connection. It's currently at version 3.0.1 and appears to be actively maintained, with a focus on POSIX-compliant operating systems.
Warnings
- breaking pdb-attach does not work on Windows operating systems. It relies on POSIX signals for its implementation, which are not available on Windows. Although it can be imported on Windows, the `listen` function will not operate, and a warning will be raised.
- gotcha The target Python process must explicitly import and call `pdb_attach.listen()` *before* you can attach to it. It cannot attach to an arbitrary, unprepared running Python process.
- gotcha Using `pdb-attach` introduces a potential security risk. It uses sockets for communication, meaning that a malicious actor with access to your machine could connect to the debugging port, inspect the running process's source code and state, and even execute arbitrary Python code.
- gotcha pdb-attach may not work correctly in multi-threaded Python applications. Breakpoints and debugging behavior can be inconsistent across threads.
- gotcha When running inside a container (e.g., Docker) and attempting to attach to a host process, `pdb-attach` might cause segmentation faults due to `ptrace(2)` relying on `struct user_regs_struct` definitions that vary between platforms.
Install
-
pip install pdb-attach
Imports
- listen
from pdb_attach import listen
- pdb_attach (command)
pdb_attach <PID> <PORT>
Quickstart
import pdb_attach
import time
import os
def my_long_running_function():
print(f"Process PID: {os.getpid()}")
print("Starting long-running function...")
pdb_attach.listen(port=5555)
print("pdb_attach is listening on port 5555. Attach with: pdb_attach PID 5555")
for i in range(100):
# Simulate work
time.sleep(1)
if i % 10 == 0:
print(f"Iteration {i}")
print("Function finished.")
if __name__ == "__main__":
my_long_running_function()