vscode调试python多线程必须启用"subprocess": true,否则子线程断点不触发、变量不可见;需使用debugpy而非ptvsd,断点打在子线程函数首行可执行语句,并通过call stack手动切换线程查看对应局部变量。

VSCode调试Python多线程应用,断点进不了子线程、变量看不到、线程卡住没反应——不是代码写错了,而是调试器默认根本不“看”子线程。必须显式告诉debugpy:请监控所有线程。
断点打在子线程函数里却完全不触发
这是最常见也最误导人的现象:你明明在def worker()第一行打了断点,threading.Thread(target=worker).start()之后程序就一路跑完,断点像不存在一样。
- 根本原因是debugpy默认只 attach 主线程,
subProcess没开,子线程等于“隐身” - 检查
launch.json是否含"subProcess": true——缺了这一项,其他都白配 - 确保用的是
debugpy(不是已弃用的ptvsd):调试控制台顶部应显示debugpy version 1.6.0+;若出现ptvsd字样,立刻执行pip uninstall ptvsd && pip install --upgrade debugpy - 断点必须落在子线程实际执行的第一行可执行语句上,比如
print("in thread"),而不是Thread(...).start()那行
Variables面板里找不到子线程的局部变量
这不是变量丢了,是你没切换调试上下文。VSCode的Variables面板永远只显示当前选中的调用栈帧,不是“所有线程变量合并视图”。
- 调试暂停后,打开左侧
CALL STACK面板,你会看到类似MainThread、Thread-1、Thread-2的条目 - 手动点击其中某一线程(比如
Thread-1),Variables面板立刻刷新为该线程的局部作用域 - 全局变量(模块级或
global声明的)在任意线程上下文中都可见,但值是最新写入状态——注意这不是快照,竞态下可能被其他线程刚改过 - 如果某线程还在
time.sleep(5)里没停住,它就不会出现在CALL STACK中,自然看不到它的局部变量——这是正常行为,不是bug
多进程调试时子进程断点变空心圆
subProcess: true对multiprocessing生效有硬性前提:子进程必须能被debugpy自动注入,而这依赖启动方式和函数可导入性。
- Windows/macOS上必须用
spawn启动方式:import multiprocessing as mp; mp.set_start_method('spawn')(Linux默认fork也可,但spawn更稳) - 入口函数(传给
Process(target=...)的那个)必须能被模块直接导入——不能是if __name__ == '__main__'块里定义的匿名函数或嵌套函数 - 加
"console": "integratedTerminal",否则子进程可能因缺少终端上下文而静默退出 - 如果仍为空心圆,检查
launch.json里是否漏了"justMyCode": false,以及PYTHONPATH是否正确指向工作区:"env": {"PYTHONPATH": "${workspaceFolder}"}
真正容易被忽略的是:每次修改launch.json后,必须彻底停止当前调试会话并重新按F5启动——继续(Continue)或重启(Restart)都不行,因为debugpy的注入逻辑只在进程启动时生效一次。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











