multiprocessing.process子进程异常不会自动回传主进程,需用pool、queue/pipe手动传递或统一用内置异常;pool.map()遇异常即中断;自定义异常需模块级定义;windows下需确保对象可pickle。

子进程崩溃时主进程收不到 traceback
默认情况下,multiprocessing.Process 里抛出的异常不会自动传回主进程,主进程只会看到子进程静默退出(exitcode != 0),但不知道哪行代码、什么错误。这是因为子进程是独立内存空间,异常对象无法跨进程序列化回传。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 用
multiprocessing.Pool替代裸Process,它默认捕获并回传异常(包括完整 traceback) - 若必须用
Process,通过multiprocessing.Queue或multiprocessing.Pipe手动把sys.exc_info()序列化后传回 - 别依赖
process.exception—— 它只在concurrent.futures.ProcessPoolExecutor中存在,multiprocessing.Process没这个属性
Pool.map() 遇到异常就整个中断
Pool.map() 是“全有或全无”语义:只要任意一个子任务抛异常,整个调用立刻终止,已成功执行的任务结果也丢弃。这和你写 for 循环时 try/except 的直觉相反。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 改用
Pool.imap()或Pool.imap_unordered(),它们返回迭代器,可逐个处理结果,并对每个结果单独 try/catch - 或者把单个任务包装成带兜底逻辑的函数,例如:
def safe_task(x): try: return heavy_work(x) except Exception as e: return {'error': str(e), 'input': x} - 注意
imap_unordered返回顺序不保证,如果顺序敏感,得自己加索引字段再排序
自定义异常类在子进程中失效
如果你定义了 class MyError(Exception),并在子进程中 raise 它,主进程收到的往往是 Exception 或 UnpicklingError,而不是原类型。因为子进程反序列化时找不到该类定义。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 所有自定义异常类必须定义在模块顶层(不能嵌套在函数或 if 块里),且被主进程 import 过
- 避免在异常中携带不可序列化的对象(如文件句柄、lambda、线程锁)
- 更稳妥的做法是统一用内置异常(
ValueError,RuntimeError),或用字符串消息 + 错误码代替类型区分
Windows 下 multiprocessing 报 PicklingError
Windows 默认用 spawn 启动方式,要求所有参与进程间传递的对象(函数、参数、返回值)都支持 pickle。常见报错:Can't pickle local object 或 AttributeError: Can't pickle module。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 确保目标函数是模块级函数(不在 class 内、不在 if __name__ == '__main__' 块外定义)
- 避免传 lambda、闭包、实例方法;改用普通函数 + 显式参数
- 在 Windows 脚本开头加
if __name__ == '__main__':保护,否则 spawn 会重复导入执行 - 不要试图用
set_start_method('fork')强切 —— Windows 不支持 fork










