【发布时间】:2014-09-16 15:34:14
【问题描述】:
在我的项目中,我使用 Python 的 multiprocessing 库在 __main__ 中创建多个进程。该项目正在使用 PyInstaller 2.1.1 打包到单个 Windows EXE 中。
我像这样创建新流程:
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__ 中:
if __name__ == '__main__':
freeze_support()
start()
不幸的是,当将应用程序打包成 EXE 并启动它时,我在这一行得到WindowsError 5 或 6(似乎是随机的):
command = queue.get_nowait()
PyInstaller 主页上的一个配方声称,在将应用程序打包为单个文件时,我必须修改我的代码以在 Windows 中启用多处理。
我在这里复制代码:
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'
我对这个“解决方案”的失望在于,第一,完全不清楚它到底在修补什么,第二,它的编写方式如此复杂,以至于无法推断出哪些部分是解决方案,哪些部分是解决方案。只是一个插图。
任何人都可以就这个问题分享一些观点,并提供见解在一个项目中究竟需要更改哪些内容,以便在 PyInstaller 构建的单文件 Windows 可执行文件中启用多处理?
【问题讨论】:
-
配方能解决问题吗?
-
嗯,目前还不清楚(至少对我来说)如何应用这个配方。仅将上述代码粘贴到我的主要 Python 脚本中也不起作用,因为它会引发另外两个与我的 Python 脚本无关的异常。这告诉我配方存在根本缺陷。
-
如果您只是将配方作为独立脚本运行,它是否可以正常运行?
-
不,我收到两个错误,一个抱怨
_MEIPASS2格式不正确,另一个抱怨 pywintypes 有问题,这是不正确的。 -
什么版本的 PyInstaller?
标签: python windows python-2.7 multiprocessing pyinstaller