オブジェクトを漬けようとするときに__slots__を定義するクラスについてエラーが発生したのはなぜですか?
質問
私は定義した(新しいスタイルの)クラスのオブジェクトを漬けようとしています。しかし、私は次のエラーを取得しています:
>>> 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__
.