我正在将一些串行处理的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)。 有什么建议?
if __name__=="__main__:"
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
THECODE.exe
对于那些对mcve感兴趣的人:仅从Multiprocessing Bomb中获取第一个代码,并使用上面的cython命令对其进行编译,将导致可执行文件崩溃。(我刚刚尝试过:-))
通过在代码示例中添加一行以显示,我发现了一些有趣的东西__name__:
__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时显示
python
__main__ __mp_main__ __mp_main__ __mp_main__ __mp_main__ __mp_main__
(其他输出被抑制)。说明if决策有效。在cython之后运行可执行文件并显示编译时
__main__ __main__ __main__ __main__ __main__ __main__
越来越多。因此,工人对模块的调用不再masqueraded像导入一样,因此每个工人都尝试以递归方式启动五个新对象。
masqueraded
我认为,根据提交的错误报告中的详细信息,我可以在此处提供最优雅的解决方案
if __name__ == '__main__': if sys.argv[0][-4:] == '.exe': setattr(sys, 'frozen', True) multiprocessing.freeze_support() YOURMAINROUTINE()
在freeze_support()需要-call在Windows上- 看到蟒蛇多处理文档。 如果仅在该行中在python中运行,则已经可以了。 但不知何故,用Cython显然是不知道的一些这些东西(的文档告诉它与测试py2exe,PyInstaller和cx_Freeze)。它可以通过setattr-call缓解,该调用仅在编译时使用,因此由文件扩展名决定。
freeze_support()
py2exe
PyInstaller
cx_Freeze
setattr