【问题标题】:Python Pickling Slots ErrorPython酸洗槽错误
【发布时间】:2011-04-01 04:01:49
【问题描述】:

我有一个大实例,我一直在酸洗就好了,但最近我在尝试转储它时开始收到此错误:

  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__。我无法隔离触发此错误的更改。

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

【问题讨论】:

标签: python pickle


【解决方案1】:

使用二进制协议进行酸洗(而不是您似乎默认使用的旧 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 会更快并且产生更紧凑的结果——您只需要确保正确保存和恢复它产生的 binary 字符串(因此,例如,如果您要腌制文件,请务必为wb 打开后者,不是只是w)。

如果由于某种原因您无法使用这种全方位的双赢解决方案,则有一些技巧和窍门(例如,子类 pickle.Pickler,直接使用您的子类的实例,而不是像 pickle.dumps 那样使用基础实例, 覆盖 save 方法,以便它在委托给超类之前跟踪 type(obj)),但升级到正确的、最新的协议(-1 保证在任何给定的 Python 版本上都是该版本支持的最先进的版本)无论如何都是一个好主意,如果可行的话。

【讨论】:

    【解决方案2】:

    我也遇到了这个问题,但是旧 ASCII 协议中有一些已经腌制的数据。 您可以使用这些方法使 slot 适应您的对象:

    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 很有用

    【讨论】:

    • __getstate____setstate__ 不需要使用 dict。因此,在分配时使用列表和带有__slots__ 的压缩文件可能是有效的。
    猜你喜欢
    • 1970-01-01
    • 2014-09-15
    • 1970-01-01
    • 1970-01-01
    • 2013-09-28
    • 2021-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多