当前位置: 首页 > 面试题库 >

PyInstaller内置的Windows EXE失败并进行多处理

司空鸿禧
2023-03-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可执行文件中的多处理功能的项目中确切需要更改什么?


问题答案:

找到这张PyInstaller票证后回答我自己的问题:

显然,我们要做的就是提供一个Process(和_Popen)类,如下所示,并使用它代替multiprocessing.Process。我已经纠正并简化了该类,使其仅可在Windows上使用,*
ix系统可能需要不同的代码。

为了完整起见,以下是上述问题的改编样本:

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


 类似资料:
  • 问题内容: 如果对某些人来说这太简单了,我感到抱歉,但是我仍然不了解python的多处理技巧。我已经阅读了 http://docs.python.org/dev/library/multiprocessing http://pymotw.com/2/multiprocessing/basics.html 以及Google给我的许多其他教程和示例…其中许多从这里也是。 好吧,我的情况是我必须计算许多

  • 我有大约5个与从HTTP获取数据以及基于数据处理和生成结果相关的任务。 我希望并行运行这些任务,并等待所有任务成功完成或其中一个任务失败。每个任务都应该能够发布失败原因。如果其中一项任务失败,那么所有任务都将被视为失败,并在不等待所有任务完成的情况下退出。 我试图使用完整的未来和未来列表来实现它,但它不起作用,代码也不能很好地发布。 我有没有更好的方法来实现它?以身作则会有所帮助。

  • 我对spark streaming有两个问题: < li >我有一个spark流应用程序正在运行,并以< code>20秒的批处理间隔收集数据,在< code>4000个批处理中,有< code>18个批处理因异常而失败: 无法计算拆分,块输入-0-1464774108087 未找到 我假设此时数据大小大于spark可用内存,并且应用程序< code>StorageLevel为< code>MEM

  • 当我构建我的项目时,我遇到了这个错误; 建立“,”sources:“[{”file:“…\app\build\intermediates\manifests\full\debug\AndroidManifest.xml”,“position:{“startine”:146}],”original:“,”tool:“:”AAPT“}错误:处理清单失败。 任务:应用程序:processDebugRes

  • tkinter程序用pyinstaller打包成单个exe后wav资源调用失败 打包时用了--add-data "a.wav;." 参数,依然不管用