当作为可执行文件冻结时,多处理运行主窗口的新实例

时间:2012-08-03 19:56:22

标签: python multiprocessing pyinstaller

一年前我已经问过this exact question。我的应用程序使用Python的多处理模块,它在从命令行运行时工作正常,但是当我使用Pyinstaller将其打包为可执行文件时,多个进程会生成为原始的新实例,而不是运行它们应该运行的函数。上次给我的建议以及我看到的其他地方的建议是在multiprocessing.freeze_support(区块的开头调用if __name__ == "__main__":,这是我一直这样做的,但是我突然遇到了这个问题又出于某种原因。还有什么可能导致这个?

更新:我已确认freeze_support()行的存在根本不会影响此问题。对它进行注释或取消注释它会产生完全相同的行为:主窗口的副本被打开并坐在那里什么都不做。这是在我的主要Python模块的最末端调用它的块:

if __name__ == '__main__':
    freeze_support()

    # (A bunch of commented-out lines)
    main()

3 个答案:

答案 0 :(得分:5)

我是个白痴。 (好吧,也许不是,但这完全是我的错)多处理通过运行它带有两个额外的参数来表示它是子进程的进程:标志--multiprocessing-fork和来自父进程的管道的数字句柄。 multiprocessing.freeze_support检查是否存在此标志,以决定是否运行为子进程或普通程序指定的函数。无论如何,我解析命令行参数的方法改变了sys.argv,它摆脱了标志并导致子进程像新的父进程一样运行。

所以,故事的寓意是,永远不会改变sys.argv。我转而使用optparse,它抱怨标志的存在,所以我不得不传递一个过滤的参数列表。一旦我这样做,问题就消失了。

答案 1 :(得分:0)

我遇到了同样的问题,但是我解决了将if子句放入代码中的问题,以避免每个奇异的代码在新进程中运行。例如:

import pickle

mydict = { 'a': 1111, 'b': 2222 }
dumped = pickle.dumps(mydict)
string_of_bytes_obj = str(dumped) # Deliberate string representation for this quick example. 

unpickled_dict = pickle.loads(dumped) 

除此之外,我所有使用kivy的类都需要放入相同的if子句中,以避免主程序中的错误。

我的结论是kivy,多处理程序和pyinstaller的交互使新窗口弹出。如果直接从python运行代码,则不会显示问题。 就我而言,我已经在使用一个if子句来导入kivy.core.window,它可以直接从python运行代码,但在pyinstaller之后不能运行,即使使用freeze_support也可以。

我希望它能对某人有所帮助。

答案 2 :(得分:0)

setup.py样式程序的其他陷阱可能导致此问题:

如果您使用入口点来启动程序,则可能需要将multiprocessing.freeze_support()放在main()内。

例如,

Pyinstaller_setuptools直接调用main(),跳过if __name__ == '__main__':块中的所有语句。