Python multiprocessing调用apply_sync后get()卡死无法获取结果
multiprocessing.Pool.apply_async()调用get()卡死解决方案 故障根因
- 核心触发点是缺少主模块入口保护:Python multiprocessing在spawn进程启动模式(Windows、macOS默认模式,IPython/Jupyter环境强制使用该模式)下,子进程启动时会重新导入主模块的全部代码。如果创建进程池、提交任务的逻辑没有放在
if __name__ == "__main__":代码块内,子进程导入主模块时会递归创建新的进程池、无限生成子进程,最终触发死锁,导致get()调用永久阻塞。 - 示例代码还存在回调函数变量名错误:回调函数
f的入参命名为res,但函数内部调用了未定义的变量r,会触发回调执行异常,无异常捕获的场景下也会阻塞结果返回。 - 如果是在Jupyter/IPython交互环境运行,额外存在交互域函数无法被子进程导入的问题:spawn模式下子进程无法直接读取notebook交互单元格中定义的函数,也会导致任务执行失败卡死。
修复后可运行代码
from multiprocessing import Pool def calrr(Data, numID): fe = 1000 fen = 5 print(f"test: {fe * fen}") return fe, numID def f(res): # 修复原代码变量名错误,将未定义的r改为入参res print("Finished", res) # 必须加主入口保护,避免子进程递归创建进程池 if __name__ == "__main__": p = Pool(2) toto = p.apply_async(calrr, args=([1], 0), callback=f) p.close() p.join() print("任务返回结果:", toto.get())
交互环境额外注意事项
如果在IPython/Jupyter中运行,需要将calrr、f这类需要被进程池调用的函数,写到单独的.py文件中,再通过import导入到notebook中使用,不要直接在交互单元格定义后传入进程池,否则子进程无法找到对应函数触发阻塞。
内容的提问来源于stack exchange,提问作者Charles Chapus
相关产品推荐
相关产品推荐

