問(wèn)題描述
我剛剛在我的程序中發(fā)現(xiàn)了一個(gè)奇怪的錯(cuò)誤,它與它使用 Python 的多處理模塊有關(guān).當(dāng)我從機(jī)器上的源代碼運(yùn)行程序時(shí),一切正常.但是我一直在使用 pyinstaller 將它構(gòu)建成一個(gè)可執(zhí)行文件,并且由于某種原因,當(dāng)我運(yùn)行從我的代碼構(gòu)建的可執(zhí)行文件時(shí),多處理的行為發(fā)生了巨大的變化.具體來(lái)說(shuō),當(dāng)我嘗試運(yùn)行我的代碼的多處理部分時(shí),而不是做它應(yīng)該做的,似乎是我的程序主窗口的副本彈出,每個(gè)進(jìn)程一個(gè).更糟糕的是,如果手動(dòng)關(guān)閉它們,它們會(huì)重新打開,大概是因?yàn)樗鼈兪?multiprocessing.pool 的一部分.不打印任何錯(cuò)誤消息,并且一旦創(chuàng)建所有窗口就坐在那里什么都不做.是什么原因造成的?
I just discovered a bizarre bug in my program related to its use of Python's multiprocessing module. Everything works fine when I run the program from the source on my machine. But I've been building it into an executable using pyinstaller, and for some reason the behavior of multiprocessing changes drastically when I run the executable built from my code. Specifically, when I try to run the multiprocessing part of my code, rather than do what it's supposed to, what appears to be a copy of my program's main window pops up, one for each process. Even worse, they reopen if they are closed manually, presumably because they are part of a multiprocessing.pool. No error messages are printed, and once created all the windows just sit there doing nothing. What could be happening to cause this?
推薦答案
在 Windows 上,multiprocessing
嘗試通過(guò)啟動(dòng)新的實(shí)例來(lái)模擬 Unix fork()
系統(tǒng)調(diào)用您的可執(zhí)行文件,并在其中執(zhí)行其子進(jìn)程例程 (multiprocessing.forking.main()
).使用標(biāo)準(zhǔn) Python 解釋器 (python.exe
),multiprocessing
可以傳遞 -c
參數(shù)來(lái)運(yùn)行自定義代碼.但是,對(duì)于自定義可執(zhí)行文件,這是不可能的,因?yàn)榭蓤?zhí)行文件很可能不支持與 python.exe
相同的命令行選項(xiàng).
On Windows, multiprocessing
tries to emulate the Unix fork()
system call by starting new instances of your executable, and execute its child process routine (multiprocessing.forking.main()
) therein. With the standard Python interpreter (python.exe
), multiprocessing
can pass the -c
parameter to run custom code. For custom executables, however, this is not be possible since the executable will most probably not support the same command line options as python.exe
.
freeze_support()
函數(shù)通過(guò)顯式執(zhí)行子進(jìn)程例程來(lái)回避這個(gè)問(wèn)題,并通過(guò)調(diào)用 sys.exit()
終止解釋器.如果忘記調(diào)用freeze_support()
,新進(jìn)程不知道自己是子進(jìn)程,運(yùn)行主應(yīng)用邏輯.在您的情況下,這將彈出另一個(gè)主 GUI 窗口.
The freeze_support()
function sidesteps this problem by executing the child process routine explicitely, and terminate the interpreter by calling sys.exit()
. If you forget to call freeze_support()
, the new process does not know that it is a child process and runs the main application logic. In your case, this will pop up another main GUI window.
由于從新創(chuàng)建的進(jìn)程啟動(dòng)另一個(gè)子進(jìn)程將導(dǎo)致無(wú)限遞歸,multiprocessing
試圖通過(guò)檢查 sys.frozen
屬性并引發(fā) RuntimeError
如果 freeze_support()
未被調(diào)用.在您的情況下,似乎需要用戶交互來(lái)生成進(jìn)程,因此沒(méi)有無(wú)限遞歸,也沒(méi)有 RuntimeError
.
Since starting yet another child process from the newly created process will cause infinite recursion, multiprocessing
tries to prevent this by checking the sys.frozen
attribute and raise a RuntimeError
if freeze_support()
was not called. In your case, it seems that user interaction is required to spawn the processes, therefore there is no infinite recursion and no RuntimeError
.
按照慣例,sys.frozen
僅設(shè)置為由 py2exe
或 PyInstaller 創(chuàng)建的自動(dòng)生成的可執(zhí)行文件.當(dāng)您想要將 Python 嵌入到應(yīng)支持 windows 下的多處理的自定義可執(zhí)行文件中時(shí),了解此邏輯并將 sys.frozen
設(shè)置為 True
非常重要.
By convention, sys.frozen
is only set for automatically generated executables as created by py2exe
or PyInstaller. It is important to understand this logic and set sys.frozen
to True
when one wants to embed Python in a custom executable that should support multiprocessing under windows.
這篇關(guān)于Python - 從可執(zhí)行文件運(yùn)行時(shí),Multiprocessing.processes 成為主進(jìn)程的副本的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!