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