У меня есть большой экземпляр, который я выбрал просто отлично, но недавно я начал получать эту ошибку, когда пытался ее сбросить:
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 __
. У меня проблемы с выделением изменения, которое я сделал, вызвавшего эту ошибку.
Я могу только предположить, что внутри моего экземпляра есть какой-то объект, который вызывает это. Есть ли способ получить больше информации? Как найти класс точного объекта, который вызывает эту ошибку?
Используйте двоичный протокол для травления (вместо старого 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
, используйте непосредственно экземпляр вашего подкласса, а не базовый one, как pickle.dumps
, переопределяет метод save
, поэтому он отслеживает тип (obj)
перед делегированием суперклассу), но при обновлении вправо, Самый современный протокол ( -1
гарантированно будет в любой данной версии Python наиболее продвинутым протоколом, который поддерживает эта версия) в любом случае будет хорошей идеей, если это вообще возможно.