debugpy¶
Language: Python · Transport: stdio
The catalog entry:
[adapters.debugpy]
id = "debugpy"
command = "python3"
args = ["-m", "debugpy.adapter"]
transport = "stdio"
python3 rather than python: a bare python usually does not exist on PATH
on macOS. The real interpreter is most often in the project's virtualenv and
arrives through adapter_command.
Install¶
debugpy is a Python module, installed into an interpreter rather than into the
system:
Two interpreters, two settings¶
This is the part that causes confusion. There are two independent choices:
| Setting | Which interpreter |
|---|---|
adapter_command |
runs the adapter |
launch_arguments.python |
runs your code |
[profiles.main]
adapter = "debugpy"
adapter_command = "${root}/.venv/bin/python"
program = "main.py"
[profiles.main.launch_arguments]
python = "${root}/.venv/bin/python"
They are usually the same interpreter, and bugsaur init writes both when it
finds .venv/bin/python or venv/bin/python in the project root. They are still
separate settings, and No module named debugpy almost always means one of them
points at an interpreter without debugpy installed.
The working directory reaches the debuggee explicitly¶
Unlike Delve, debugpy does not pass its own working directory down to the
debuggee by inheritance. Bugsaur sends the working directory in the DAP request
body, which is why the project root reliably becomes the debuggee's directory —
and why imports of a package under src/ resolve without a cwd line.
Debugging a module¶
debugpy accepts module. There is no profile field for it; use the escape
hatch:
[profiles.tests]
adapter = "debugpy"
program = "."
args = ["-x", "tests/"]
[profiles.tests.launch_arguments]
module = "pytest"
Django and other reloaders¶
An autoreloader forks a second process that the debugger is not attached to, so breakpoints in the worker never fire. Disable it:
The same applies to any framework with a reload-on-change mode — uvicorn's
--reload, Flask's debug reloader.
Diagnostics¶
| Symptom | Cause | Fix |
|---|---|---|
No module named debugpy |
installed into a different interpreter | install into the one in adapter_command |
| Session never starts | adapter_command points at a nonexistent path |
check the venv path |
| Breakpoints never fire | an autoreloader forked a second process | --noreload |
ImportError for your own package |
the working directory is not what the code assumes | Working directory |
| Stops only in library code | the exception came from deeper | Call Stack |