如何通过multiprocessing.Process传递对象实例?遇Pickle报错
解决方案:解决multiprocessing中lambda无法pickle的问题
1. 用具名函数替换lambda
这是最直接的方案——pickle能序列化模块级别的具名函数,但处理不了匿名lambda。如果你的Routes类里用lambda做简单包装,直接替换成具名函数或者直接存储原始函数引用即可。
原始问题代码示例(典型写法):
class Routes: def __init__(self): self.route_map = {} def route(self, path): def decorator(view_func): # 此处lambda无法被pickle序列化 self.route_map[path] = lambda request: view_func(request) return view_func return decorator
修改后代码:
# 定义具名包装函数(如果需要额外包装逻辑) def view_wrapper(view_func): def wrapper(request): # 原来lambda里的逻辑移到此处 return view_func(request) return wrapper class Routes: def __init__(self): self.route_map = {} def route(self, path): def decorator(view_func): # 用具名函数替代lambda self.route_map[path] = view_wrapper(view_func) # 若不需要包装,直接存原始函数即可:self.route_map[path] = view_func return view_func return decorator
2. 改用dill替代默认pickle序列化
dill是扩展了pickle的第三方库,能序列化lambda、嵌套函数等pickle处理不了的对象。
步骤:
- 安装dill:
pip install dill - 在代码中替换multiprocessing的默认序列化器:
import multiprocessing as mp import dill # 替换默认pickler为dill mp.reduction.ForkingPickler = dill.Pickler mp.reduction.dump = dill.dump # 正常启动进程 if __name__ == '__main__': server = Server() server_process = mp.Process(target=server.run) server_process.start() # 关闭进程示例 # server_process.terminate() # server_process.join()
注意:Windows系统下multiprocessing默认用spawn模式,需确保所有业务代码都在if __name__ == '__main__':块内,避免重复初始化。
3. 调整架构:子进程内初始化Server实例
不要把主进程的Server实例传递给子进程,而是在子进程内部根据配置重新创建Server,完全避开对象序列化的问题。
代码示例:
import multiprocessing as mp def start_server(server_config): # 子进程内独立创建Server实例并启动 server = Server(**server_config) server.run() if __name__ == '__main__': # 定义Server配置参数 config = { 'host': '127.0.0.1', 'port': 8080, # 其他自定义配置项 } # 启动子进程 server_process = mp.Process(target=start_server, args=(config,)) server_process.start() # 需要关闭时执行 server_process.terminate() server_process.join()
这个方案更稳定,跨进程传递复杂对象本来就容易引发问题,子进程独立初始化能减少耦合,也避免了序列化相关的各种坑。
内容的提问来源于stack exchange,提问作者Alex Jando
相关产品推荐
相关产品推荐

