2010-08-19 73 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