2010-08-19 21 views
10

tengo un gran ejemplo que he estado decapado muy bien, pero recientemente comenzó a recibir este error cuando traté de tirarla:Python Decapado ranuras de error

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 

No entiendo este error, ya que todas mis clases parecen definir un método __getstate__, y ninguna parece definir __slots__. Estoy teniendo problemas para aislar el cambio que hice el desencadenado este error.

Solo puedo suponer que hay un objeto anidado en mi instancia que está causando esto. ¿Hay alguna forma de obtener más información? ¿Cómo encuentro la clase del objeto exacto que desencadena este error?

+0

http://stackoverflow.com/questions/2204155/why-am-i- get-a-error-about-my-class-defining-slots-when-trying-to-pickl –

Respuesta

11

Use un protocolo binario para su decapado (en lugar del antiguo ASCII al que parece estar incumpliendo) y todo irá bien. Observe:

>>> 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 
>>> 

Como se ve, la -1 protocolo (que significa "el mejor, más rápido y más protocolo compacto") funciona bien, mientras que el protocolo predeterminado 0 (el protocolo ASCII de edad diseñado para ser compatible con todas las camino de regreso a Python 1.5 y anteriores) da exactamente la excepción que ha observado.

Además, -1 será más rápido y producir resultados más compactos - sólo tiene que asegurarse de que correctamente guardar y restaurar los binarios cuerdas que produce (así, por ejemplo, si usted está decapado para presentar, asegúrese de abrir el último para wb, no solo w).

Si por alguna razón esta solución todo-en torno de ganar-no está disponible para usted, hay hacks y trucos (por ejemplo, subclase pickle.Pickler, utilizar directamente una instancia de la subclase en lugar de la base de uno pickle.dumps hace, anulará la save método por lo que rastrea el type(obj) antes de delegar a la superclase), pero la actualización a la derecha, el protocolo más actualizado (-1 está garantizado que, en cualquier versión dada de Python, la más avanzada compatible con la versión) sería una buena idea de todos modos, si es posible.

0

Tuve este problema también pero con algunos datos ya encurtidos en el antiguo protocolo ASCII. Puede utilizar estos métodos para adaptarse a su ranura de objeto:

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) 

que de puede ser útil para ganar cantidad de RAM

+1

'__getstate__' y' __setstate__' no necesitan usar un 'dict'. Entonces, puede ser eficiente usar una lista y un zip con '__slots__' en la asignación. – SimplyKnownAsG

Cuestiones relacionadas