Ubuntu、cx_Freeze 和 multiprocessing.Manager() 在“spawn”类型进程的情况下发生冲突

Posted

技术标签:

【中文标题】Ubuntu、cx_Freeze 和 multiprocessing.Manager() 在“spawn”类型进程的情况下发生冲突【英文标题】:Ubuntu, cx_Freeze and multiprocessing.Manager() conflict in case "spawn" type processes 【发布时间】:2020-05-30 08:27:29 【问题描述】:

环境:

Ubuntu - 18.04 Python - 3.6.6 cx_Freeze - 6.1

代码:

简单的 ma​​in_script.py 文件(存储库中的示例 - https://github.com/Yuriy-Leonov/cython_multiprocessing_issue)

import multiprocessing

if __name__ == '__main__':
    print("step-1")
    multiprocessing.set_start_method("spawn")
    print("step-2")
    multiprocessing.freeze_support()
    print("step-3")
    manager = multiprocessing.Manager()
    print("step-4")
    s_dict = manager.dict()
    print("finish")

setup.py(用于 cx_Freeze):

import cx_Freeze

executables = [cx_Freeze.Executable("main_script.py")]

cx_Freeze.setup(
    name="Example",
    options=
        "build_exe": 
            "replace_paths": [("*", "")]
        ,
    ,
    executables=executables
)

问题:

通过命令python setup.py build 构建可执行文件后,我运行了它,控制台日志包含以下内容:

step-1
step-2
step-3
step-1
step-2
step-3
step-1
step-2
step-3
...

产生了无限的进程。 我知道multiprocessing.Manager() 应该产生“服务器”进程。但无法了解当前行为以及如何强制它创建“共享字典”

重要:

multiprocessing.set_start_method("spawn") 由于主程序行为,无法更改和需要。

问题:

如何在当前配置中创建manager.dict()

PS:

如果使用常规python <filename>(明显)运行没有问题

【问题讨论】:

如果它是一个纯 python 脚本并使用 cython 编译它会产生与在常规 python 解释器下运行不同的运行时行为,那么我认为它定义为 cython 中的一个错误。 github.com/cython/cython/issues/3262 似乎相关 我试图改进我在***.com/a/47360452/5769463 中的回答。因为它适用于任何冻结的 Python 脚本,而不仅仅是 Cython - 它显示出了什么问题,引用了尚未解决的错误条目,还提出了一个自己动手的解决方案,它至少可以作为一个很好的起点. 【参考方案1】:

了解set_start_method("spawn") 的作用很重要。

将脚本作为预编译的可执行文件运行并期望set_start_method("spawn") 正常工作是没有意义的,因为"spawn" 在这里的意思是“通过重新调用解释器来启动我的子进程”,但“解释器”是你的预编译程序!

当你运行你的程序时,你会得到一个 fork 炸弹,因为多处理模块试图产生以下进程:

$ ./main_script --multiprocessing-fork tracker_fd=6 pipe_handle=8
$ ./main_script -S -E -c 'from multiprocessing.semaphore_tracker import main;main(5)'

这不适用于您的预编译程序。如果您希望set_start_method("spawn") 工作,您需要将exec 显式地添加到python 解释器中或处理这些情况。

【讨论】:

好吧,实际上对于 Windows,即使使用“预编译”,这段代码也能正常工作。

以上是关于Ubuntu、cx_Freeze 和 multiprocessing.Manager() 在“spawn”类型进程的情况下发生冲突的主要内容,如果未能解决你的问题,请参考以下文章

MultiPeer 框架避免使用 MCBrowserView?

连接浏览器和广告商而不在 Multipeer 连接中显示警报消息

在c ++中使用multipe recv()和send()调用

当用户关闭和打开蓝牙时,Multipeer Connectivity 停止工作

Multipeer Connectivity 自动静默连接

从 Connecting 到 NotConnected 的 Multipeer Connectivity 会话