18

スクリプトの再コンパイルによってクラス定義が更新された後、pickle はそのクラスの以前にインスタンス化されたオブジェクトのシリアル化を拒否し、次のエラーを表示します: "Can't pickle object: it's not the same object as "

そのような場合を無視する必要があることをピクルに伝える方法はありますか? クラスを名前で識別するだけで、不一致の原因となっている内部の一意の ID を無視しますか?

この問題を便利で堅牢な方法で解決する代替の同等のモジュールの提案を答えとして歓迎します。


参考までに、私の志望動機は次のとおりです。

私は、Python スクリプトをライブで編集できる、生産性の高い迅速なイテレーション開発環境を作成しています。スクリプトは繰り返し再コンパイルされますが、データはコンパイル間で保持されます。生産性の目標の一環として、私はシリアル化に pickle を使用しようとしています。これにより、データ構造が常に変化するための明示的なシリアル化コードを作成および更新するコストを回避できます。

ほとんどの場合、組み込み型をシリアル化します。私はピクルするクラスで意味のある変更を避けるように注意しており、必要に応じて copy_reg.pickle メカニズムを使用して unpickle でアップコンバージョンを実行します。

スクリプトの再コンパイルにより、クラス定義が実際には変更されていない (または変更が無害な方法でのみ変更されている) 場合でも、オブジェクトをピクルすることがまったくできなくなります。

4

3 に答える 3

12

以前のバージョンのクラス定義をアンパックできない限り、インスタンスをダンプしてロードする必要がある参照 pickle はなくなりました。だからこれは「ありえない」。

ただし、やりたい場合は、クラス定義の以前のバージョンを保存できます...そして、古い/保存されたクラス定義を参照するようにpickleをだまして、最新のもの - これは単に編集するobj.__class__obj.__module__、古いクラスを指すだけかもしれません。クラスインスタンスには、処理する必要がある古いクラス定義を参照する他の奇妙なものがある場合もあります。また、クラス メソッドを追加または削除すると、予期しない結果が発生するか、それに応じてインスタンスを更新する必要があります。もう 1 つの興味深いひねりは、unpickler が常にクラスの最新バージョンを使用できるようにすることです。

私のシリアル化パッケージdillには、コンパイルされたソースをライブ コード オブジェクトから一時ファイルにダンプし、その一時ファイルを使用してシリアル化できるメソッドがいくつかあります。これはパッケージの新しい部分の 1 つであるため、残りの dill ほど堅牢ではありません。また、あなたのユースケースは私が検討したユースケースではありませんが、それがどのように優れた機能になるかはわかりました.

于 2013-10-14T14:42:39.240 に答える
2

2つの解決策が頭に浮かびます:

  1. 漬ける前に設定できますobject.__class__

    >>> class X(object):
        pass
    
    >>> class Y(object):
        pass
    
    >>> x = X()
    >>> x.__class__ = Y
    >>> type(x)
    <class '__main__.Y'>
    

    persistent_idすべてのオブジェクトが渡されるため、これを使用できるかもしれません。

  2. __reduce__pickle とまったく同じように定義します。(これについては pickle.py を見てください)

于 2013-04-29T14:53:26.787 に答える