vscode python异步调试需设"type": "python"、"justmycode": false,用breakpoint()替代ui断点,uvicorn/fastapi须用module模式启动并禁用热重载。

launch.json 里 type 必须是 "python",不是 "pwa-python"
VSCode 的 Python 调试器靠 type 字段决定用哪个适配器。异步调试也一样——如果写成 "type": "pwa-python"(旧版遗留)或误填为 "node",断点会静默失效,控制台不报错,但程序一路跑完。
验证方式很简单:启动调试时看左下角状态栏是否显示 “Python Debugging”;或者在代码行号左侧点击,出现实心红点且悬停提示 “Breakpoint set”,才算识别成功。
- 不要从 Node.js 或其他语言项目复制
launch.json后直接改名了事 - 确保只启用官方
ms-python.python扩展,禁用冲突的第三方 Python 插件 - 工作区根目录下只能有一个有效的
.vscode/launch.json,多层嵌套时 VSCode 可能加载错路径下的配置
asyncio 代码必须用 breakpoint() 或显式设置断点
VSCode 默认调试器对 await 表达式、async for 循环和事件循环调度的支持有限。单纯在 await some_coro() 行设断点,经常跳过——因为那行本身不执行,只是挂起协程。
更可靠的做法是把断点打在协程函数内部、或在关键逻辑前插入 breakpoint():
async def fetch_data():
await asyncio.sleep(1)
data = {"status": "ok"}
breakpoint() # 这里能稳停
return data
-
breakpoint()是 Python 3.7+ 原生调试入口,比 UI 断点更贴近运行时上下文 - 避免在顶层
asyncio.run()调用处设断点,它只是启动器,不包含业务逻辑 - 若用
uvicorn或fastapi,需额外配置"subProcess": true,否则子进程里的异步逻辑无法 attach
多线程 + 异步混合场景要关掉 justMyCode
当代码同时用到 threading.Thread 和 asyncio(比如后台线程发 HTTP 请求、主线程 await 结果),默认 "justMyCode": true 会让调试器跳过标准库和第三方包中的协程调度逻辑,导致断点卡在 event loop 外围,进不了实际 handler。
把 justMyCode 设为 false,才能看到 asyncio.events、concurrent.futures 等模块里的调用栈:
{
"name": "Python: Async + Thread",
"type": "python",
"request": "launch",
"module": "main",
"justMyCode": false,
"console": "integratedTerminal"
}
- 副作用是变量面板会多出大量标准库变量,需要手动折叠无关作用域
- 调试结束后建议切回
true,避免日常开发时信息过载 - 配合
"logToFile": true查看 debugpy 日志,搜索"coroutine"或"task"关键词可确认是否真正进入了协程上下文
Uvicorn/FastAPI 调试必须用 module 模式而非 program
直接运行 main.py 无法触发 FastAPI 的异步生命周期——Uvicorn 是通过 importlib 动态导入 app 实例并注册事件循环的。用 "program": "${file}" 会导致 app 变量未被正确暴露给 Uvicorn 的 loader。
正确做法是用 module 启动模式,并指定 Uvicorn 入口:
{
"name": "FastAPI: Debug",
"type": "python",
"request": "launch",
"module": "uvicorn",
"args": [
"main:app",
"--host", "127.0.0.1",
"--port", "8000",
"--reload=false"
],
"console": "integratedTerminal"
}
-
--reload=false必须加,否则热重载会 fork 子进程,主调试器 attach 不上 -
main:app中的app必须是顶层变量,不能是函数返回值或类实例属性 - 确保终端当前路径是
main.py所在目录,否则import main会失败
异步调试最难的不是配置,而是判断“到底停在哪一层”——event loop、task、coroutine、thread 四层上下文容易混淆。每次断点没生效,先查 type 和 justMyCode,再确认是不是该用 breakpoint() 替代 UI 断点。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











