【发布时间】:2022-02-16 09:24:34
【问题描述】:
我正在使用pickle 库来序列化一个自定义对象,我们称之为A,它在a.py 中定义。
如果我在a.py 中腌制A 类型的对象,如下所示:
import pickle
class A:
...
if __name__ == "__main__":
inst = A("some param")
with open("a.pickle", 'wb') as dumpfile:
pickle.dump(inst, dumpfile)
如果模块 A 未明确在命名空间 __main__ 中,则从存储加载此对象时会出现问题。见this other question。这是因为pickle 知道它应该在__main__ 中查找类A,因为那是pickle.dump() 发生的地方。
现在,有两种方法可以解决这个问题:
- 在反序列化端处理它,
- 在序列化结束时处理。
对于1,有多种选择(例如,请参见上面的链接),但我想避免这些,因为我认为让“pickler”对其数据负责是有意义的.
对于2,当模块位于__main__ 命名空间下时,我们可以避免酸洗,但这似乎不太灵活。我们也可以修改A.__module__,并将其设置为模块的名称(就像here一样)。
Pickle 使用这个__module__ 变量来查找从哪里导入A 类,所以在 .dump() 工作之前设置它:
if __name__ == "__main__":
inst = A("some param")
A.__module__ = 'a'
with open("a.pickle", 'wb') as dumpfile:
pickle.dump(inst, dumpfile)
问:这是个好主意吗?似乎它依赖于实现,而不是依赖于接口。也就是说,pickle 可以决定使用另一种定位要导入的模块的方法,这种方法会失败。有没有使用pickle接口的替代方案?
【问题讨论】:
-
@JacquesGaudin 谢谢,该问题中提供的
dill可能是一个不错的选择。我不知何故错过了这个问题,无论是在早期还是在回顾这个问题时。很高兴作为指向那里的重复关闭,但也许有一些关于修改__module__的见解?