Python存储自定义对象构成的字典的最优方法是什么?
报错原因
你遇到的cannot pickle 'weakref' object错误,本质是Trainer实例中隐含了来自Discord SDK的不可序列化弱引用对象:你在初始化Trainer时传入的user是Discord SDK返回的对象,即使你看起来只取了三个基础属性,要么是你不小心把整个user对象绑定到了Trainer实例上,要么是部分Discord对象的属性本身携带了无法被pickle识别的弱引用标记。
最优存储方案
推荐你使用JSON序列化方案,相比修复pickle问题,JSON方案可读性更高、不受类结构迭代影响、不存在序列化安全风险,适配你的轻量本地存储需求,实现步骤如下:
第一步:给两个自定义类增加序列化/反序列化方法
import json class Character: def __init__(self, slot, name, skills, item=None): self.slot = slot # int self.name = name # str self.skills = skills # 字符串组成的字典 self.item = item # str def to_dict(self): return { "slot": self.slot, "name": self.name, "skills": self.skills, "item": self.item } @classmethod def from_dict(cls, data): return cls(**data) class Trainer: # 优化初始化逻辑,不要直接传入Discord的user对象,只传需要的基础属性,从根源避免引入不可序列化对象 def __init__(self, user_id, name, icon): self.id = user_id # int self.name = name # str self.icon = icon # 图片url字符串 self.team = [] # Character实例组成的列表 def to_dict(self): return { "id": self.id, "name": self.name, "icon": self.icon, "team": [char.to_dict() for char in self.team] } @classmethod def from_dict(cls, data): trainer = cls( user_id=data["id"], name=data["name"], icon=data["icon"] ) trainer.team = [Character.from_dict(char_data) for char_data in data["team"]] return trainer
注:实例化Trainer时单独取出user.id/user.name/user.icon三个基础值传入即可,彻底规避弱引用问题
第二步:实现master字典的存储和读取
存储代码
# 序列化master字典为可JSON存储的结构 serializable_master = { str(user_id): trainer.to_dict() for user_id, trainer in master.items() } with open("master.json", "w", encoding="utf-8") as f: json.dump(serializable_master, f, ensure_ascii=False, indent=2)
读取代码
with open("master.json", "r", encoding="utf-8") as f: serializable_master = json.load(f) # 反序列化为原对象结构 master = { int(user_id): Trainer.from_dict(trainer_data) for user_id, trainer_data in serializable_master.items() }
如果一定要用pickle方案,只需要按照上面的优化方式修改Trainer的初始化逻辑,不要在实例中留存任何Discord SDK返回的对象引用,就能解决弱引用无法序列化的问题,但依然更推荐JSON方案,更适合你的轻量本地存储场景。
内容的提问来源于stack exchange,提问作者Roopesh-J
相关产品推荐
相关产品推荐

