debugpy 是微软开发的 Python 调试器,遵循 DAP 协议。VS Code 的 Python 扩展底层就是调用它——本地调试自动调用,远程调试与无 IDE 场景需手动配置。
核心特性
- DAP 协议:统一 IDE 与调试器通信规范,兼容 VS Code、PyCharm 等
- 远程调试:通过 socket 连接服务器/容器中的 Python 应用
- 多进程支持:原生支持
multiprocessing - Jupyter 集成:可调试 Notebook 代码单元
何时需要显式使用
| 场景 | 是否需要手动配置 | 原因 |
|---|---|---|
| VS Code 本地调试 | 不需要 | Python 扩展自动调用 |
| 命令行直接调试 | 需要 | 无 IDE 介入 |
| 远程服务器调试 | 需要 | 需启动服务端等待连接 |
| Docker 容器调试 | 需要 | 容器内需运行 debugpy 服务 |
| Jupyter Notebook | 需要 | 手动嵌入调试监听 |
| PyCharm 调试 | 不需要 | PyCharm 内置调用 |
debugpy 的价值主要在 远程调试 与 无 IDE 环境;本地开发由 IDE 自动管理。
安装
pip install debugpy命令行直接调试(无 IDE)
# 直接运行并监听
python -m debugpy --listen 5678 script.py
# 等待外部调试器连接(如 VS Code attach)
python -m debugpy --listen 5678 --wait-for-client script.py任何支持 DAP 协议的工具都可以连接。
本地调试
VS Code 的 Python 扩展底层就是调用 debugpy。配置 "type": "python" 后按 F5:
用户按 F5 → VS Code Python 扩展 → 自动启动 debugpy → 调试 Python 进程调试器与被调试程序在同一进程空间,VS Code 通过 DAP 协议与 debugpy 通信。
launch.json
.vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: 当前文件",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"justMyCode": true,
"env": {"PYTHONUNBUFFERED": "1"}
},
{
"name": "Python: 模块调试",
"type": "python",
"request": "launch",
"module": "my_package.main",
"console": "integratedTerminal"
},
{
"name": "Python: 带参数",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/app.py",
"args": ["--config", "dev.yaml"],
"console": "integratedTerminal"
}
]
}关键配置
| 配置项 | 说明 | 示例 |
|---|---|---|
program | 调试目标文件 | ${file} |
module | 模块方式启动 | my_package.main |
args | 命令行参数 | ["--debug", "true"] |
env | 环境变量 | {"DEBUG": "1"} |
cwd | 工作目录 | ${workspaceFolder} |
console | 控制台类型 | integratedTerminal / externalTerminal |
justMyCode | 仅调试用户代码 | true(跳过库代码) |
调试操作
- 断点:点行号左侧添加;右键可设条件断点(如
i > 10)、日志断点、触发断点 - 执行控制:F5 继续 / F10 单步跳过 / F11 单步进入 / Shift+F11 跳出 / Shift+F5 停止
- 变量监视:在”变量”面板查看;自定义表达式加到”监视”面板
远程调试
代码运行在远程服务器、Docker 容器或 SSH 环境,本地 IDE attach 到远程进程。
工作原理
┌──────────────┐ ┌────────────────┐
│ 本地 VS Code │ ←── socket ──→ │ 远程 Python 进程│
│ (客户端) │ 5678 │ (debugpy 服务)│
└──────────────┘ └────────────────┘服务端(被调试方)
# 命令行启动
python -m debugpy --listen 0.0.0.0:5678 --wait-for-client app.py或代码内嵌:
import debugpy
debugpy.listen(("0.0.0.0", 5678))
print("等待调试器附加...")
debugpy.wait_for_client() # 阻塞直到 VS Code 连接
# 业务代码继续执行...| 参数 | 说明 |
|---|---|
--listen 0.0.0.0:5678 | 监听所有接口,允许外部连接 |
--listen localhost:5678 | 仅监听本地,需配合 SSH 隧道 |
--wait-for-client | 启动后等待调试器连接才继续执行 |
客户端(VS Code)
{
"name": "Python: 远程附加",
"type": "python",
"request": "attach",
"connect": {
"host": "192.168.1.100",
"port": 5678
},
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "/opt/project"
}
]
}路径映射
本地代码路径与远程运行路径不同,VS Code 需要映射才能正确关联断点。
| 场景 | localRoot | remoteRoot |
|---|---|---|
| 项目结构相同 | ${workspaceFolder} | /app |
| 子目录映射 | ${workspaceFolder}/src | /app/src |
| Windows → Linux | C:\\dev\\project | /home/user/project |
SSH 隧道(推荐)
直接暴露调试端口有安全风险。SSH 隧道把端口收口到本地:
ssh -L 5678:localhost:5678 user@remote-serverVS Code 改连本地:
"connect": {"host": "localhost", "port": 5678}Docker 容器调试
docker-compose.yml:
services:
app:
image: python:3.11
volumes:
- ./src:/app
ports:
- "5678:5678"
command: python -m debugpy --listen 0.0.0.0:5678 --wait-for-client /app/main.pyVS Code 配置:
{
"name": "Python: Docker 调试",
"type": "python",
"request": "attach",
"connect": {"host": "localhost", "port": 5678},
"pathMappings": [
{"localRoot": "${workspaceFolder}/src", "remoteRoot": "/app"}
]
}本地 vs 远程对比
| 维度 | 本地 | 远程 |
|---|---|---|
| 启动方式 | VS Code 直接启动 | 程序独立启动,VS Code 附加 |
request | launch | attach |
| 路径映射 | 不需要 | 必须 |
| 适用 | 日常开发 | 生产复现、容器调试 |
| 启动速度 | 快 | 较慢(需建立连接) |
Jupyter Notebook
import debugpy
debugpy.listen(5678)
# VS Code 执行 "Python: 远程附加" 后,可在 Notebook 内调试故障排除
| 问题 | 原因 | 解决 |
|---|---|---|
| 远程连接失败 | 端口未开放 / 防火墙阻拦 | 开放端口;确认监听 0.0.0.0 |
| 断点灰色(未命中) | 路径映射错误 | 检查 pathMappings 对应关系 |
| 调试卡死 | 死锁 / 库代码阻塞 | 设置 justMyCode: false 看完整栈 |
| 无法进入函数 | justMyCode 跳过库代码 | 设置 justMyCode: false |
| 多进程调试失败 | 子进程未配置 | 加 "subProcess": true |
最佳实践
- 开发:本地调试,快速迭代
- 环境问题排查:远程调试到真实环境
- Docker:端口映射 + 路径映射,保留本地编辑体验
- 生产:始终走 SSH 隧道,避免暴露调试端口
- 复杂项目:模块启动(
module)优于文件启动(program)