2010-08-19 57 views
10

我有一个大的情况下,我一直在酸洗就好了,但最近我开始收到此错误,当我试图转储:Python的酸洗槽错误

File "/usr/lib/python2.6/copy_reg.py", line 77, in _reduce_ex 
    raise TypeError("a class that defines __slots__ without " 
TypeError: a class that defines __slots__ without defining __getstate__ cannot be pickled 

我不明白这个错误,因为我所有的课程似乎都定义了一个__getstate__方法,而且似乎也没有定义__slots__。我无法隔离导致此错误的更改。

我只能假设有一些对象嵌套在我的实例中,导致这一点。有什么方法可以获得更多信息?我如何找到触发此错误的确切对象的类?

+0

http://stackoverflow.com/questions/2204155/why-am-i-我的班级定义插槽试图挑选 – 2017-01-16 15:33:37

回答

11

为你的酸洗使用二进制协议(而不是旧的ASCII,你似乎是默认的),你会没事的。注意:

>>> class ws(object): 
... __slots__ = 'a', 'b' 
... def __init__(self, a=23, b=45): self.a, self.b = a, b 
... 
>>> x = ws() 
>>> import pickle 
>>> pickle.dumps(x, -1) 
'\x80\x02c__main__\nws\nq\x00)\x81q\x01N}q\x02(U\x01aq\x03K\x17U\x01bq\x04K-u\x86q\x05b.' 
>>> pickle.dumps(x) 
Traceback (most recent call last): 
    [[snip]] 
    File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/copy_reg.py", line 77, in _reduce_ex 
    raise TypeError("a class that defines __slots__ without " 
TypeError: a class that defines __slots__ without defining __getstate__ cannot be pickled 
>>> 

正如你看到的,-1协议(意为“最好,最快,最紧凑的协议”)工作得很好,而默认0协议(旧的ASCII协议设计为兼容所有回到Python 1.5和更早的版本)给出了你所观察到的异常。

此外,-1会更快产生更紧凑的结果 - 你只需要确保你正确地保存和恢复二进制字符串它产生(因此,举例来说,如果你酸洗到文件,请务必打开后者wb,而不是只是w)。

如果由于某种原因,这个全能双赢的解决方案是不提供给你,有黑客和技巧(如子pickle.Pickler,用你的子类的直接实例,而不是基地之一的pickle.dumps确实,覆盖save方法,以便在委托给超类之前跟踪type(obj)),但升级到最新的最新协议(-1保证在任何给定的Python版本中是版本支持的最高级版本)将是无论如何,如果可行的话,这是一个好主意。

0

我也有这个问题,但一些已经在旧的ASCII协议腌制的数据。 您可以使用这些方法来适应槽,以你的对象:

class MyAlreadyPickeldObjectWithslots(object): 
    ___slots__= ("attr1","attr2",....) 
    def __getstate__(self): 
     return dict([(k, getattr(self,k,None)) for k in self.__slots__]) 

    def __setstate__(self,data): 
     for k,v in data.items(): 
      setattr(self,k,v) 

这可能是有用的,以获得的RAM量

+1

'__getstate__'和'__setstate__'不需要使用'dict'。因此,在分配时使用'__slots__'来使用列表和zip可能是有效的。 – SimplyKnownAsG 2016-06-27 22:38:59