为什么在VS Code的集成Python调试中启动了多个调试线程?

Why are multiple debugging threads being started in integrated Python-debugging of VS Code?

** 更新**

来自 a related discussion 我得到了以下答案:

Also, something to double check in your code is if the main entry point is protected by the __name__=='__main__' check:

if __name__ == '__main__':
    main()

and depending on the structure, you could also need the multiprocessing.freeze_support() if you need to have multiprocessing support:

i.e.:

if __name__ == '__main__':
    multiprocessing.freeze_support()
    main()

(if you don't have that structure, it may explain why multiprocessing is executing your main entry point code multiple times).

然而,我既没有实施上述第一个选项,也没有实施上述第二个选项,而且,我执行的任何脚本都可能发生这种突然的多线程行为。 似乎 old/previous 调试会话并没有真正在幕后终止,因为在一个会话中没有多线程,然后在调试时启动了一个多会话。 正常执行代码时也会发生这种情况,它会因错误而退出,然后我(再次)进入调试会话。

我不确定如何实现它,但我应该把

if __name__ == '__main__':
    multiprocessing.freeze_support()
    main()

在我作为主脚本执行的所有 python 脚本的开头,即我的入口点或顶级脚本?

** 原始问题 **

随附的屏幕截图中可以看到,在执行标准调试过程时,通过按F5 VS Code(之前定义了一些断点),偶尔会发生以下情况:

这会导致大量额外的计算时间、滞后和冗余的控制台输出,因为相同的代码会连续执行多次。

奇怪的是,这种行为似乎是随机发生的。只有有时我可以得出结论,我之前曾尝试启动调试会话,该会话在代码中的某个时刻被 Uncaught Exception 中断,但对我来说,为什么 VS Code 应该重新启动似乎仍然不合逻辑当按下 F5.

时,所有这些先前失败的调试会话以及一个新的调试会话

当通过Shift+F5或红色方块按钮Stop中断调试过程时,有时VS Code右下角会出现timeout after 1000 ms消息-window;特别是当问题发生时在 call stack.

中显示多个不需要的子进程和线程

我的 launch.json - 定义集成终端调试的文件的相关部分是:

{
    // !!THIS CONFIG-FILE IS USED FOR DEBUGGING!!
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Current File (Integrated Terminal)",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            // VS Code Integrated Terminal. If redirectOutput is set to True, output is also displayed in the debug console.
            "console": "integratedTerminal",
            // Make sure that code output is also being displayed in the debug console.
            "redirectOutput": true,
            // When omitted or set to true (the default), restricts debugging to user-written code only. Set to false to also enable debugging of standard library functions.
            "justMyCode": false
        },
...

至于 settings.json - 文件,除了通用选项 "debug.allowBreakpointsEverywhere": true.

我想首先了解为什么会出现这种不受欢迎的调试行为,最后能够阻止它的发生。


PS 尝试在 official GitHub of VS Code 上获得答案:

我已经提交了一份 issue on the VS Code GitHub-page,但有人建议我在 Whosebug 上提问,因为

"VS Code only shows what is being requested by the Python debugger."

您的代码是多线程的还是您过去调试的这些进程(但这些进程没有按预期被终止)?

就我个人而言,我在执行 运行 -> 开始调试时没有观察到这个问题 - 我认为这与 F5 相同。

这就是我的调用堆栈部分以及我的 launch.json 的样子。完成调试会话后,请务必点击停止或断开连接按钮。

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Current File",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal"
        }
    ]
}

我找到了解决方案 in this thread

总而言之,

建议在主脚本的末尾(即执行开始的开始entry-script)执行以下内容:

if __name__ == '__main__':
    multiprocessing.freeze_support()
    main()

multiprocessing.freeze_support() 不会在 UNIX-systems 上执行 harm/nothing,但会在 Windows 上执行。 如果reader喜欢了解更多in-depth关于这个功能的知识, 见上面提到的GitHub-discussion的docs and this part

尽管是必不可少的部分(参见 here

is calling main() from "under the guard"

其中“守卫”代表 if __name__ == '__main__':

此外,如前所述here

it should generally be at the end of your script, and all top-level code that's not already in a function should be inside main(). The reason is that your script is going to be imported as a module in every subprocess that multiprocessing spawns, so any top-level code will run many times without the guard. But only the instance that's directly started as a script will have __name__ == "__main__".