Python 3.X环境下Multiprocessing调用Boost Python封装代码Pickling错误求助
报错信息:
multiprocessing.pool.MaybeEncodingError: Error sending result: '<multiprocessing.pool.ExceptionWithTraceback object at 0x7ff19e308f40>'. Reason: 'PicklingError("Can't pickle <class 'Boost.Python.ArgumentError'>: import of module 'Boost.Python' failed")'
报错根因
Python 3的multiprocessing库默认使用pickle协议完成进程间的参数、返回值、异常对象序列化,而Boost.Python生成的扩展类型(包括上述报错中的Boost.Python.ArgumentError异常类)默认没有实现pickle序列化协议。Python 2.7中使用的旧版pickle协议对C扩展类型的兼容逻辑更宽松,因此不会触发报错,Python 3收紧了序列化校验规则才会出现该问题。
可行解决方案
- 方案一:替换序列化后端(改动最小)
直接使用第三方库multiprocess替代标准库的multiprocessing,该库是标准库multiprocessing的分支,默认使用dill序列化器,支持大部分C扩展类型的序列化,无需修改业务逻辑,仅需把代码中所有import multiprocessing的语句替换为import multiprocess as multiprocessing即可。 - 方案二:避免传递Boost.Python类型对象
本次报错是子进程返回的异常为Boost.Python专属类型导致,可在子进程执行的目标函数外层加异常捕获逻辑,把所有Boost.Python抛出的异常转换为Python原生异常后再抛出,同时入参、返回值均提前转换为Python原生类型(dict、list、字符串、数值等),避免任何Boost封装的对象在进程间传递。示例代码如下:def wrapped_boost_func(*args, **kwargs): try: res = your_boost_func(*args, **kwargs) # 将Boost类型返回值转换为Python原生类型后再返回 return convert_to_native_type(res) except Exception as e: # 捕获Boost.Python异常,转换为原生RuntimeError抛出 if "Boost.Python" in str(type(e)): raise RuntimeError(f"Boost函数执行错误: {str(e)}") raise - 方案三:给Boost封装类注册pickle支持
如果你有权限修改Boost.Python的封装代码,可以给所有需要跨进程传递的类、异常类型用boost::python::pickle_suite定义序列化/反序列化逻辑,重新编译生成Python 3版本的封装包即可从根源解决序列化问题。 - 方案四:换用无序列化的进程间通信方式
改用共享内存、本地套接字等方式传递数据,仅传递原生类型的执行状态和结果,完全绕开pickle序列化的限制。
内容的提问来源于stack exchange,提问作者Adam G.
相关产品推荐
相关产品推荐

