gpt4 book ai didi

python - 为什么我在尝试 pickle 对象时收到关于定义 __slots__ 的类的错误?

转载 作者:IT老高 更新时间:2023-10-28 22:12:12 27 4
gpt4 key购买 nike

我正在尝试 pickle 我定义的(新型)类的对象。但我收到以下错误:

>>> with open('temp/connection.pickle','w') as f:
... pickle.dump(c,f)
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "/usr/lib/python2.5/pickle.py", line 1362, in dump
Pickler(file, protocol).dump(obj)
File "/usr/lib/python2.5/pickle.py", line 224, in dump
self.save(obj)
File "/usr/lib/python2.5/pickle.py", line 331, in save
self.save_reduce(obj=obj, *rv)
File "/usr/lib/python2.5/pickle.py", line 419, in save_reduce
save(state)
File "/usr/lib/python2.5/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/usr/lib/python2.5/pickle.py", line 649, in save_dict
self._batch_setitems(obj.iteritems())
File "/usr/lib/python2.5/pickle.py", line 663, in _batch_setitems
save(v)
File "/usr/lib/python2.5/pickle.py", line 306, in save
rv = reduce(self.proto)
File "/usr/lib/python2.5/copy_reg.py", line 76, in _reduce_ex
raise TypeError("a class that defines __slots__ without "
TypeError: a class that defines __slots__ without defining __getstate__ cannot be pickled

我没有在类里面明确定义 __slots__。我所做的事情是否隐含地定义了它?我该如何解决这个问题?我需要定义 __getstate__ 吗?

更新: gnibbler选择了一个很好的例子。我试图 pickle 的对象的类包装了一个套接字。 (我现在想到)套接字定义 __slots__ 而不是 __getstate__ 是有充分理由的。我假设一旦一个进程结束,另一个进程就不能解开并使用前一个进程的套接字连接。所以当我接受 Alex Martelli的优秀答案,我将不得不采用与 pickle 不同的策略来“共享”对象引用。

最佳答案

定义 __slots__ 的类(而不是 __getstate__ )可以是您的祖先类,也可以是您的属性或项目的类(或祖先类),直接或间接:本质上,有向图中任何对象的类 以您的对象为根的引用,因为 pickle 需要保存整个图形。

一个简单的解决方案是使用协议(protocol)-1,这意味着“最好的协议(protocol)pickle可以使用”;默认是一个古老的基于 ASCII 的协议(protocol),它对 __slots____getstate__ 施加了这种限制。考虑:

>>> class sic(object):
... __slots__ = 'a', 'b'
...
>>> import pickle
>>> pickle.dumps(sic(), -1)
'\x80\x02c__main__\nsic\nq\x00)\x81q\x01.'
>>> pickle.dumps(sic())
Traceback (most recent call last):
[snip snip]
raise TypeError("a class that defines __slots__ without "
TypeError: a class that defines __slots__ without defining __getstate__ cannot be pickled
>>>

如您所见,协议(protocol) -1 大步前进了 __slots__,而默认协议(protocol)给出了与您看到的相同的异常。

协议(protocol)-1的问题:它产生一个二进制字符串/文件,而不是像默认协议(protocol)那样的ASCII码;由此产生的 pickle 文件将无法被足够古老的 Python 版本加载。除了 __slots__ 的关键之一之外,优点还包括更紧凑的结果和更好的性能。

如果您被迫使用默认协议(protocol),那么您需要准确确定哪个类给您带来麻烦以及确切原因。如果是这种情况,我们可以讨论策略(但如果你可以使用 -1 协议(protocol),那就更好了,不值得讨论;-)和简单的代码检查寻找麻烦的类/对象被证明太复杂了(我想到了一些基于 deepcopy 的技巧来获得整个图的可用表示,以防你想知道)。

关于python - 为什么我在尝试 pickle 对象时收到关于定义 __slots__ 的类的错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2204155/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com