下面链接的文档似乎说顶层类可以被腌制,以及它们的实例。但根据我之前的question的答案,它似乎不正确。在我发布的脚本中,pickle接受了类对象并写了一个文件,但这没用。
这是我的问题:这个文档是错误的,还是有些更微妙的我不明白?此外,在这种情况下,pickle应该生成某种错误消息吗?
https://docs.python.org/2/library/pickle.html#what-can-be-pickled-and-unpickled,
可以腌制以下类型:
- 无,真,假
- 整数,长整数,浮点数,复数
- 普通和Unicode字符串
- 仅包含可选对象的元组,列表,集和词典
- 在模块顶层定义的功能
- 在模块顶层定义的内置函数
- 在模块顶层定义的类(我的粗体)
- 此类的实例 dict 或调用 getstate ()>的结果是可选择的(详见“泡菜协议”一节)。
答案 0 :(得分:4)
创建一个在模块顶层定义的类:
<强> foo.py 强>:
class Foo(object): pass
然后运行一个单独的脚本,
<强> script.py 强>:
import pickle
import foo
with open('/tmp/out.pkl', 'w') as f:
pickle.dump(foo.Foo, f)
del foo
with open('/tmp/out.pkl', 'r') as f:
cls = pickle.load(f)
print(cls)
打印
<class 'foo.Foo'>
请注意,pickle文件out.pkl
仅包含 strings ,它们命名定义模块和类的名称。它不存储类的定义:
cfoo
Foo
p0
.
因此,在取消时,定义模块foo
必须包含类的定义。如果从定义模块中删除该类
del foo.Foo
然后你就会收到错误
AttributeError: 'module' object has no attribute 'Foo'
答案 1 :(得分:1)
完全有可能在python中挑选一个类实例...同时还保存代码以重建类和实例的状态。如果你想在pickle
之上破解一个解决方案,或者使用&#34;特洛伊木马&#34;这里基于exec
的方法是如何做到的:
How to unpickle an object whose class exists in a different namespace (python)?
或者,如果你使用dill
,你有一个dump
函数已经知道如何存储类实例,类代码和实例状态:
How to recover a pickled class and its instances
Pickle python class instance plus definition
我是dill
作者,我创建dill
部分是为了能够在multiprocessing
之间发送类实例和类方法。
Can't pickle <type 'instancemethod'> when using python's multiprocessing Pool.map()