为何multiprocessing挂起而multiprocess可正常运行
multiprocessing.Pool与multiprocess.Pool核心差异 两者API完全1:1对齐,替换时无需修改业务逻辑代码,核心差异集中在底层实现和兼容性上:
- 底层序列化逻辑不同
标准库multiprocessing跨进程传参靠内置的pickle模块做序列化,pickle支持的对象范围非常有限:lambda表达式、嵌套定义的函数、Jupyter/IPython这类交互环境里写的函数、pandas的Series行对象这类复杂结构,它都无法正常序列化。最影响排查的是这类序列化失败经常不会抛出明确异常,直接表现为进程池永久挂起,和你遇到的现象完全一致。
第三方库multiprocess跨进程传参用的是dill序列化引擎,几乎能序列化所有Python对象,没有上述限制,这也是你只修改导入的库名,代码就直接恢复正常的核心原因。 - 交互环境适配能力不同
multiprocessing的子进程需要靠导入主模块的方式拿到你定义的任务函数和参数,如果你不是运行本地写好的.py脚本,而是在Jupyter、IPython或者Python交互式命令行里写代码,子进程根本找不到对应的主模块路径,很容易直接卡死无响应。multiprocess不需要走主模块导入的逻辑,直接把序列化好的完整任务传给子进程,不管是跑脚本还是在交互环境里使用,行为完全一致。 - 分发维护主体不同
multiprocessing是Python官方维护的标准库,装完Python就自带,不需要额外安装。multiprocess是社区维护的第三方库,需要手动执行pip install multiprocess安装,设计初衷就是补全标准库多进程模块的序列化短板,所以所有接口、参数都和标准库保持一致,替换成本为0。
你遇到的挂起问题,本质就是传入任务的参数(
df.iterrows()生成的pandas行对象)或是自定义的call_runner函数无法被pickle正常序列化,子进程收不到有效任务一直处于等待状态,主进程等待子进程返回结果就会一直卡住。换成用dill做序列化的multiprocess之后,序列化环节的障碍被清除,代码自然就能正常运行。
内容的提问来源于stack exchange,提问作者Laura
相关产品推荐
相关产品推荐

