2010-08-19 19 views
10

Ben sadece iyi dekapaj oldum geniş örneği var, ama bunu dökümü çalıştığımda geçenlerde bu hatayı almaya başladı tüm sınıflarım __getstate__ yöntemini tanımladığı için ve hiçbiri __slots__ tanımlamıyor gibi görünüyor. Bu hatayı tetiklediğim değişikliği yalıtmakta sorun yaşıyorum.Python Dekapaj Yuvaları Hata

Sadece benim örneğimin içinde yer alan bazı nesnelerin buna neden olduğunu varsayabilirim. Daha fazla bilgi almak için herhangi bir yolu var mı? Bu hatayı tetikleyen tam nesnenin sınıfını nasıl bulabilirim?

+0

http://stackoverflow.com/questions/2204155/why-am-i- sınıfım-tanımlayan-yuvaları-alırken-alırken-pick-to-pickl –

cevap

11

Dekapajınız için bir ikili protokol kullanın (varsayılan olarak eski ASCII yerine) ve iyi olacaksınız. Gözlemleyin:

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

Gördüğünüz gibi, -1 protokolü (anlamına gelen "En iyi, en hızlı ve kompakt bir protokol en"), gayet güzel çalışıyor iken varsayılan 0 protokolü (uyumlu olacak şekilde tasarlanmıştır eski ASCII protokolü bütün Python 1.5 ve daha öncesine geri dönüş) tam olarak gözlemlediğiniz istisnayı verir.

yanında

, -1ve daha kompakt sonuçlar daha hızlı olacaktır - sadece doğru sizi temin kaydedip (ürettiği ikili dizeleri geri yüklemeniz gerekir böylece, örneğin, dosyaya dekapaj eğer, ikincisini, , değil sadece w) açtığınızdan emin olun. nedense bu her çevrede-kazan çözümü sizin için kullanılabilir durumda değilse

, kesmek ve hileler (örneğin alt sınıf pickle.Pickler yerine tabanın daha da alt sınıfının doğrudan bir örneğini kullanmak vardır, geçersiz kılıyor pickle.dumps gibi bir save yöntemini kullanarak, süper sınıfa devredilmeden önce type(obj)'u izler, ancak sağa, en güncel protokole (-1, sürümün desteklediği en gelişmiş herhangi bir Python sürümünde olması garantilenir) Yine de, eğer uygunsa, iyi bir fikir.

0

Eski ASCII protokolünde önceden hazırlanmış verilerle de bu sorunu yaşadım. Sen nesneye yuvası uyarlamak için bu yöntemleri kullanabilirsiniz: en yararlı olabilir

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 miktarını kazanmak için

+1

'__getstate__' ve' __setstate__' bir 'dict' kullanmaya gerek yoktur. Yani, bir liste kullanmak ve atama sırasında __slots__' ile zip kullanmak etkili olabilir. – SimplyKnownAsG