一尘不染

使用cython的dask或joblib多重处理编译可执行文件会导致错误

python

我正在将一些串行处理的python作业转换为dask或joblib的多处理程序。可悲的是我需要在Windows上工作。
从IPython内部运行或从命令行调用python的py文件时,一切运行良好。
使用cython编译可执行文件时,它不再能正常运行:越来越多的进程(无限且大于请求的进程数)逐步启动并阻塞我的系统。
感觉就像多处理炸弹一样-但我当然使用if __name__=="__main__:"过控制块-通过在命令行上从python调用中正常运行来批准。
我的cython调用是的cython --embed --verbose --annotate THECODE.PY,我正在编译以gcc -time -municode -DMS_WIN64 -mthreads -Wall -O -I"PATH_TO_\include" -L"PATH_TO_\libs" THECODE.c -lpython36 -o THECODE生成Windows可执行文件THECODE.exe
与其他(单个处理)代码一起运行良好。
这个问题对于dask和joblib似乎是相同的(可能意味着dask的工作方式类似于Joblib或基于Joblib)。
有什么建议?

对于那些对mcve感兴趣的人:仅从Multiprocessing
Bomb中获取第一个代码,并使用上面的cython命令对其进行编译,将导致可执行文件崩溃。(我刚刚尝试过:-))

通过在代码示例中添加一行以显示,我发现了一些有趣的东西__name__

import multiprocessing

def worker():
    """worker function"""
    print('Worker')
    return

print("-->" + __name__ + "<--")
if __name__ == '__main__':
    jobs = []
    for i in range(5):
        p = multiprocessing.Process(target=worker)
        jobs.append(p)
        p.start()

当运行这段代码python时显示

__main__
__mp_main__
__mp_main__
__mp_main__
__mp_main__
__mp_main__

(其他输出被抑制)。说明if决策有效。在cython之后运行可执行文件并显示编译时

__main__
__main__
__main__
__main__
__main__
__main__

越来越多。因此,工人对模块的调用不再masqueraded像导入一样,因此每个工人都尝试以递归方式启动五个新对象。


阅读 209

收藏
2021-01-20

共1个答案

一尘不染

我认为,根据提交的错误报告中的详细信息,我可以在此处提供最优雅的解决方案

if __name__ == '__main__':
    if sys.argv[0][-4:] == '.exe':
        setattr(sys, 'frozen', True)
    multiprocessing.freeze_support()
    YOURMAINROUTINE()

freeze_support()需要-call在Windows上-
看到蟒蛇多处理文档
如果仅在该行中在python中运行,则已经可以了。
但不知何故,用Cython显然是不知道的一些这些东西(的文档告诉它与测试py2exePyInstallercx_Freeze)。它可以通过setattr-call缓解,该调用仅在编译时使用,因此由文件扩展名决定。

2021-01-20