2010-08-19 2 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- get-an-error-about-my-class-define-slots-when-try-to-pickl –

ответ

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) 

Это может быть полезно, чтобы получить объем оперативной памяти

+1

'__getstate__' и' __setstate__' не нужно использовать 'dict'. Таким образом, может быть эффективным использовать список и zip с '__slots__' при назначении. – SimplyKnownAsG