Python多进程调用其他类实例方法出现PicklingError如何解决?
多智能体Env类封装多进程Pickle错误解决方案
问题根因
- Windows平台下Python默认
multiprocessing库使用spawn模式创建子进程,要求进程间传递的函数、参数、返回值都可以被pickle序列化 - 你将
job定义为Env的普通成员方法时,self.job是绑定了当前Env实例的方法,序列化时会连带整个Env实例(包括内部的agents列表、所有picos相关对象)一起序列化,而picos库内部定义的lambda函数无法被pickle识别 - 你当前
Agent.Optimisation方法返回的字典中直接包含picos的求解器对象、picos矩阵对象,这些对象内部携带的lambda是报错的直接诱因
解决方案
方案1:原生库兼容方案(无额外依赖)
步骤1:优化Agent返回值,剔除所有picos原生对象
将返回值中所有picos类型的变量转为Python原生数据类型(列表、浮点数、整数等),不需要的求解器对象直接不返回:
class Agent: def __init__(self): # 原有初始化逻辑 pass def Optimisation(self): # 原有求解逻辑 decision_agent = { # 不要返回opt_prob等picos原生对象 "q_us_val": q_us_val.np.tolist(), # picos矩阵转Python列表 "q_ds_val": float(q_ds_val), # 单值转Python浮点数 "p_net_exp_val": p_net_exp_val.np.tolist(), # 其余字段全部按上述规则转换,不要保留任何picos对象 } return decision_agent
步骤2:将Env的job方法改为静态方法,避免绑定Env实例
静态方法不需要序列化整个Env对象,只需要序列化方法本身和传入的agent参数:
import multiprocessing as mp from Agent import Agent class Env: def __init__(self): self.agents = [] # 环境中的智能体实例列表 @staticmethod def job(instance): return instance.Optimisation() def community_output(self): with mp.Pool(processes=4) as pool: agents_output = pool.map(self.job, self.agents) # 原有基于agents_output计算community_output的逻辑 return community_output
方案2:第三方序列化兼容方案(改造成本最低)
使用pathos库替代原生multiprocessing,它使用dill作为序列化工具,支持序列化lambda、实例方法等绝大多数pickle无法处理的对象:
- 安装依赖:
pip install pathos
- 修改Env类代码:
from pathos.multiprocessing import ProcessingPool from Agent import Agent class Env: def __init__(self): self.agents = [] # 环境中的智能体实例列表 def job(self, instance): return instance.Optimisation() def community_output(self): pool = ProcessingPool(nodes=4) agents_output = pool.map(self.job, self.agents) pool.close() pool.join() # 原有基于agents_output计算community_output的逻辑 return community_output
该方案不需要修改Agent的返回值,也不需要将job改为静态方法,适配性更强。
注意事项
Windows平台下所有多进程逻辑的入口必须放在if __name__ == '__main__'的保护块内,否则会出现子进程反复创建的问题。
内容的提问来源于stack exchange,提问作者Chaimaa
相关产品推荐
相关产品推荐

