オブジェクトを漬けようとするときに__slots__を定義するクラスについてエラーが発生したのはなぜですか?

StackOverflow https://stackoverflow.com/questions/2204155

  •  18-09-2019
  •  | 
  •  

質問

私は定義した(新しいスタイルの)クラスのオブジェクトを漬けようとしています。しかし、私は次のエラーを取得しています:

>>> with open('temp/connection.pickle','w') as f:
...   pickle.dump(c,f)
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/usr/lib/python2.5/pickle.py", line 1362, in dump
    Pickler(file, protocol).dump(obj)
  File "/usr/lib/python2.5/pickle.py", line 224, in dump
    self.save(obj)
  File "/usr/lib/python2.5/pickle.py", line 331, in save
    self.save_reduce(obj=obj, *rv)
  File "/usr/lib/python2.5/pickle.py", line 419, in save_reduce
    save(state)
  File "/usr/lib/python2.5/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/usr/lib/python2.5/pickle.py", line 649, in save_dict
    self._batch_setitems(obj.iteritems())
  File "/usr/lib/python2.5/pickle.py", line 663, in _batch_setitems
    save(v)
  File "/usr/lib/python2.5/pickle.py", line 306, in save
    rv = reduce(self.proto)
  File "/usr/lib/python2.5/copy_reg.py", line 76, in _reduce_ex
    raise TypeError("a class that defines __slots__ without "
TypeError: a class that defines __slots__ without defining __getstate__ cannot be pickled

私は明示的に定義しませんでした __slots__ 私のクラスで。私がしていることは暗黙的にそれを定義しましたか?これを回避するにはどうすればよいですか?定義する必要がありますか __getstate__?

アップデート: Gnibbler 良い例を選びました。私が漬け込もうとしているオブジェクトのクラスは、ソケットを包みます。 (それは今私に発生します)ソケットは定義します __slots__ そしてそうではありません __getstate__ 正当な理由があります。プロセスが終了すると、別のプロセスが未処理ではなく、以前のプロセスのソケット接続を使用できないと思います。だから私が受け入れている間 アレックス・マルテリの素晴らしい答えは、オブジェクトリファレンスを「共有」するために漬物とは異なる戦略を追求する必要があります。

役に立ちましたか?

解決

定義するクラス __slots__ (そしてそうではありません __getstate__)あなたの祖先クラス、またはあなたの属性またはアイテムのクラス(または祖先クラス)のいずれか、直接的または間接的にすることができます。 指示されたグラフ 漬物がグラフ全体を保存する必要があるため、ルートとしてのオブジェクトを参照する参照の。

あなたの困惑に対する簡単な解決策は、プロトコルを使用することです -1, 、これは「最高のプロトコルピクルスが使用できる」を意味します。デフォルトは、この制限を課す古代のASCIIベースのプロトコルです __slots__ vs __getstate__. 。検討:

>>> class sic(object):
...   __slots__ = 'a', 'b'
... 
>>> import pickle
>>> pickle.dumps(sic(), -1)
'\x80\x02c__main__\nsic\nq\x00)\x81q\x01.'
>>> pickle.dumps(sic())
Traceback (most recent call last):
  [snip snip]
    raise TypeError("a class that defines __slots__ without "
TypeError: a class that defines __slots__ without defining __getstate__ cannot be pickled
>>> 

ご覧のとおり、プロトコル -1 を取ります __slots__ ストライドとして、デフォルトのプロトコルはあなたが見たのと同じ例外を与えます。

プロトコルの問題 -1: :デフォルトのプロトコルのようなASCIIのものではなく、バイナリ文字列/ファイルを生成します。結果の漬物ファイルは、Pythonの十分に古いバージョンでロード可能ではありません。重要なWRTに加えて、利点 __slots__, 、よりコンパクトな結果とより良いパフォーマンスを含めます。

デフォルトのプロトコルを使用することを余儀なくされている場合、どのクラスがトラブルとその理由を正確に識別する必要があります。これが事実であれば戦略について議論することができます(しかし、あなたがおそらく使用できる場合 -1 プロトコル、それは議論する価値がないほどはるかに優れています;-)そして、厄介なクラス/オブジェクトを探している単純なコード検査は複雑すぎることが証明されています(グラフ全体の使用可能な表現を取得するためのいくつかのディープコピーベースのトリックを念頭に置いています。あなたが疑問に思っている場合)。

他のヒント

おそらく、インスタンスの属性が使用されています __slots__

例えば、 socket もっている __slots__ だから、それは漬物ではありません

どの属性がエラーを引き起こしているかを特定し、自分の属性を書く必要があります__getstate____setstate__ その属性を無視する

から PEP 307:

__getstate__ メソッドは、オブジェクト自体を参照せずにオブジェクトの状態を表す選択可能な値を返す必要があります。いいえの場合 __getstate__ 方法が存在し、返品するデフォルトの実装が使用されます self.__dict__.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top