問題描述
在我的項目中,我使用 Python 的 multiprocessing
庫在 __main__ 中創建多個進程.該項目正在使用 PyInstaller 2.1.1 打包到單個 Windows EXE 中.
In my project I'm using Python's multiprocessing
library to create multiple processes in __main__. The project is being packaged into a single Windows EXE using PyInstaller 2.1.1.
我像這樣創建新流程:
from multiprocessing import Process
from Queue import Empty
def _start():
while True:
try:
command = queue.get_nowait()
# ... and some more code to actually interpret commands
except Empty:
time.sleep(0.015)
def start():
process = Process(target=_start, args=args)
process.start()
return process
在 __main__ 中:
And in __main__:
if __name__ == '__main__':
freeze_support()
start()
不幸的是,在將應用程序打包成 EXE 并啟動它時,我在這一行得到 WindowsError
5 或 6(似乎是隨機的):
Unfortunately, when packaging the application into an EXE and launching it, I get WindowsError
5 or 6 (seems random) at this line:
command = queue.get_nowait()
PyInstaller 主頁上的一個配方聲稱,在將應用程序打包為單個文件時,我必須修改我的代碼以在 Windows 中啟用多處理.
A recipe at PyInstaller's homepage claims that I have to modify my code to enable multiprocessing in Windows when packaging the application as a single file.
我在這里復制代碼:
import multiprocessing.forking
import os
import sys
class _Popen(multiprocessing.forking.Popen):
def __init__(self, *args, **kw):
if hasattr(sys, 'frozen'):
# We have to set original _MEIPASS2 value from sys._MEIPASS
# to get --onefile mode working.
# Last character is stripped in C-loader. We have to add
# '/' or '\' at the end.
os.putenv('_MEIPASS2', sys._MEIPASS + os.sep)
try:
super(_Popen, self).__init__(*args, **kw)
finally:
if hasattr(sys, 'frozen'):
# On some platforms (e.g. AIX) 'os.unsetenv()' is not
# available. In those cases we cannot delete the variable
# but only set it to the empty string. The bootloader
# can handle this case.
if hasattr(os, 'unsetenv'):
os.unsetenv('_MEIPASS2')
else:
os.putenv('_MEIPASS2', '')
class Process(multiprocessing.Process):
_Popen = _Popen
class SendeventProcess(Process):
def __init__(self, resultQueue):
self.resultQueue = resultQueue
multiprocessing.Process.__init__(self)
self.start()
def run(self):
print 'SendeventProcess'
self.resultQueue.put((1, 2))
print 'SendeventProcess'
if __name__ == '__main__':
# On Windows calling this function is necessary.
if sys.platform.startswith('win'):
multiprocessing.freeze_support()
print 'main'
resultQueue = multiprocessing.Queue()
SendeventProcess(resultQueue)
print 'main'
我對這個解決方案"的失望在于,第一,完全不清楚它到底在修補什么,第二,它的編寫方式如此復雜,以至于無法推斷出哪些部分是解決方案,哪些部分是解決方案.只是一個插圖.
My frustration with this "solution" is that, one, it's absolutely unclear what exactly it is patching, and, two, that it's written in such a convoluted way that it becomes impossible to infer which parts are the solution, and which are just an illustration.
任何人都可以就這個問題分享一些觀點,并提供見解在一個項目中究竟需要更改哪些內容,以便在 PyInstaller 構建的單文件 Windows 可執行文件中啟用多處理?
Can anyone share some light on this issue, and provide insight what exactly needs to be changed in a project that enables multiprocessing in PyInstaller-built single-file Windows executables?
推薦答案
找到這個PyInstaller后回答我自己的問題票:
顯然我們所要做的就是提供一個如下所示的Process
(和_Popen
)類,并使用它來代替multiprocessing.Process
.我已更正并簡化了該類,使其僅適用于 Windows,*ix 系統可能需要不同的代碼.
Apparently all we have to do is provide a Process
(and _Popen
) class as shown below, and use it instead of multiprocessing.Process
. I've corrected and simplified the class to work on Windows only, *ix systems might need different code.
為了完整起見,以下是上述問題的改編樣本:
For the sake of completeness, here's the adapted sample from the above question:
import multiprocessing
from Queue import Empty
class _Popen(multiprocessing.forking.Popen):
def __init__(self, *args, **kw):
if hasattr(sys, 'frozen'):
os.putenv('_MEIPASS2', sys._MEIPASS)
try:
super(_Popen, self).__init__(*args, **kw)
finally:
if hasattr(sys, 'frozen'):
os.unsetenv('_MEIPASS2')
class Process(multiprocessing.Process):
_Popen = _Popen
def _start():
while True:
try:
command = queue.get_nowait()
# ... and some more code to actually interpret commands
except Empty:
time.sleep(0.015)
def start():
process = Process(target=_start, args=args)
process.start()
return process
這篇關于PyInstaller 構建的 Windows EXE 因多處理而失敗的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!