Python - 从可执行文件运行时,Multiprocessing.processes变成主进程的副本

8 投票
1 回答
6620 浏览
提问于 2025-04-16 23:38

我最近在我的程序中发现了一个奇怪的bug,这个问题和Python的多进程模块有关。当我在我的电脑上直接运行程序时,一切都正常。但是,当我使用pyinstaller把它打包成一个可执行文件后,程序的多进程行为却发生了很大的变化。具体来说,当我尝试运行代码中的多进程部分时,程序并没有按预期工作,而是每个进程都会弹出一个看起来像我程序主窗口的复制品。更糟糕的是,如果我手动关闭这些窗口,它们会重新打开,可能是因为它们属于一个多进程池。没有任何错误信息被打印出来,一旦这些窗口创建出来,它们就静静地在那里什么也不做。这可能是什么原因导致的呢?

1 个回答

12

在Windows系统上,multiprocessing模块试图模仿Unix系统中的fork()调用,它通过启动你程序的新实例来实现,并在其中执行子进程的相关代码(multiprocessing.forking.main())。对于标准的Python解释器(python.exe),multiprocessing可以传递-c参数来运行自定义代码。但是,对于自定义的可执行文件,这种方式可能行不通,因为这些可执行文件通常不支持和python.exe一样的命令行选项。

freeze_support()函数通过明确执行子进程的代码来解决这个问题,并通过调用sys.exit()来终止解释器。如果你忘记调用freeze_support(),新创建的进程就不知道自己是一个子进程,会直接运行主程序的逻辑。这种情况下,会弹出另一个主界面的窗口。

由于从新创建的进程再启动另一个子进程会导致无限递归,multiprocessing会通过检查sys.frozen属性来防止这种情况,如果没有调用freeze_support(),就会抛出RuntimeError。在你的情况中,似乎需要用户的操作才能启动进程,因此不会出现无限递归,也不会有RuntimeError

根据惯例,sys.frozen只会在自动生成的可执行文件中设置,比如通过py2exe或PyInstaller创建的文件。理解这个逻辑很重要,当你想在自定义的可执行文件中嵌入Python并支持Windows下的多进程时,需要将sys.frozen设置为True

撰写回答