SharedMemoryManager进程通信传自定义类触发EOFError问题咨询
报错的核心原因
Python 的 multiprocessing 模块在创建子进程时(尤其是 spawn 启动模式,Windows 默认使用,macOS/Linux 高版本也默认启用),传递给子进程的所有参数都需要经过 pickle 序列化,子进程收到后再反序列化还原对象。
你第一段代码报错的直接原因是:你把包含 SharedMemoryManager 实例的自定义 Cls 对象直接作为参数传给了子进程。SharedMemoryManager 是主进程中负责管理共享内存生命周期的服务端对象,本身不支持序列化,pickle 尝试打包这个对象时直接失败,就会抛出 EOFError: Ran out of input 错误。
第二段代码正常运行的原因
你调整后传递给子进程的是 SharedMemoryManager 创建的 ShareableList 对象,这个类是官方专门设计用来跨进程传递的共享容器,它内部只存储了共享内存的名称、偏移量、长度等访问必要的元信息,完全支持 pickle 序列化。子进程收到序列化后的 ShareableList 后,可以直接通过元信息关联到对应的共享内存区域,正常读写数据。
你把 Cls 实例的初始化放到子进程内部执行,也避免了跨进程传递不可序列化的 SharedMemoryManager 实例的问题,自然不会报错。
两种实现的核心差异
- 第一种实现跨进程传递的是持有
SharedMemoryManager实例的自定义类对象:管理器对象不可序列化,直接导致序列化失败报错 - 第二种实现跨进程传递的是管理器创建的
ShareableList实例:共享容器本身支持序列化,且类初始化在子进程内完成,没有不可序列化对象的跨进程传递操作,所以运行正常
注意:永远不要直接跨进程传递
SharedMemoryManager、multiprocessing.Manager这类管理器本身的实例,仅需要传递它们创建的共享对象(ShareableList、共享数组、共享字典等)即可,这类共享对象都是官方实现了序列化逻辑的,可安全跨进程传输。
内容的提问来源于stack exchange,提问作者Junseong

