問題描述
我剛剛在我的程序中發現了一個奇怪的錯誤,它與它使用 Python 的多處理模塊有關.當我從機器上的源代碼運行程序時,一切正常.但是我一直在使用 pyinstaller 將它構建成一個可執行文件,并且由于某種原因,當我運行從我的代碼構建的可執行文件時,多處理的行為發生了巨大的變化.具體來說,當我嘗試運行我的代碼的多處理部分時,而不是做它應該做的,似乎是我的程序主窗口的副本彈出,每個進程一個.更糟糕的是,如果手動關閉它們,它們會重新打開,大概是因為它們是 multiprocessing.pool 的一部分.不打印任何錯誤消息,并且一旦創建所有窗口就坐在那里什么都不做.是什么原因造成的?
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
嘗試通過啟動新的實例來模擬 Unix fork()
系統調用您的可執行文件,并在其中執行其子進程例程 (multiprocessing.forking.main()
).使用標準 Python 解釋器 (python.exe
),multiprocessing
可以傳遞 -c
參數來運行自定義代碼.但是,對于自定義可執行文件,這是不可能的,因為可執行文件很可能不支持與 python.exe
相同的命令行選項.
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()
函數通過顯式執行子進程例程來回避這個問題,并通過調用 sys.exit()
終止解釋器.如果忘記調用freeze_support()
,新進程不知道自己是子進程,運行主應用邏輯.在您的情況下,這將彈出另一個主 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.
由于從新創建的進程啟動另一個子進程將導致無限遞歸,multiprocessing
試圖通過檢查 sys.frozen
屬性并引發 RuntimeError
如果 freeze_support()
未被調用.在您的情況下,似乎需要用戶交互來生成進程,因此沒有無限遞歸,也沒有 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
僅設置為由 py2exe
或 PyInstaller 創建的自動生成的可執行文件.當您想要將 Python 嵌入到應支持 windows 下的多處理的自定義可執行文件中時,了解此邏輯并將 sys.frozen
設置為 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.
這篇關于Python - 從可執行文件運行時,Multiprocessing.processes 成為主進程的副本的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!