3

私の問題は、カスタム クラスが pickle.dump で保存されていることです。これらのファイルが保存されたため、カスタム クラスが変更され、pickle.load を使用するとこのエラーが発生します。保存したファイルに問題はありませんか?

エラー:

File "/cprprod/extern/lib/python2.7/pickle.py", line 1378, in load
return Unpickler(file).load()
File "/cprprod/extern/lib/python2.7/pickle.py", line 858, in load
dispatch[key](self)
file "/cprprod/extern/lib/python2.7/pickle.py", line 1070, in load_inst
self._instantiate(klass, self.marker())
File "/cprprod/extern/lib/python2.7/pickle.py", line 1060, in _instantiate
value = klass(*args)

ファイルをロードするためにできることはありますか?

コード

file = open(filename,'rb')
obj = pickle.load(file)

エラーが表示されます。


エラーを再現できる最小限のコードを次に示します。

import pickle

class foo:
    def __init__(self,a):
        self.a = a

    def __str__(self):
        return str(self.a)

obj = foo(1)

with open('junk','wb') as f:
    pickle.dump(obj,f)

class foo:
    def __init__(self,a,b):
        self.a = a
        self.b = b
    def __str__(self):
        return '%s %s'%(self.a,self.b)

    def __getinitargs__(self):
        return (self.a,self.b)

with open('junk','rb') as f:
    obj = pickle.load(f)
    print str(obj)
4

3 に答える 3

2

追加__getinitargs__()した場合は、新しいクラスがに渡された引数を処理できるかどうかを確認するのはあなた次第です__init__()。データがない古いデータで__getinitargs____init__呼び出されますが、引数はありません。

__init__キーワード引数を介してオプションの引数を作成します。

def __init__(self, otherarg=None):
    if otherarg is None:
        # created from an old-revision pickle. Handle separately.
        # The pickle will be loaded *normally* and data will still be set normally
        return
    self.otherarg = otherarg

古いスタイルのピクルスをロードするとき、これらのクラスのデータは引き続き復元されます。__setstate__()必要に応じて、を使用して内部状態を変換できます。

または、クラスからメソッドを一時的に削除します。__getinitargs__

initargs = foo.__getinitargs__.__func__
del foo.__getinitargs__
obj = pickle.load(f)
foo.__getinitargs__ = initargs

そして、現在ロードされているオブジェクトからピクルスを復元して再ダンプします__getinitargs__

私は両方のメソッドをテストしましたが、どちらの場合も古いデータが正しく読み込まれ、オブジェクトを新しいピクルスファイル __getinitargs__問題なくダンプできます。

于 2013-01-09T15:53:34.590 に答える
2

質問であなたに代わって投稿した不自然なコードを考えると、このエラーを次のように「修正」できます。

with open('junk','rb') as f:
    try:
        obj = pickle.load(f)
    except Exception as e:
        print e
        position = f.tell()
        a = foo.__getinitargs__
        del foo.__getinitargs__
        f.seek(position)
        obj = pickle.load(f)
        foo.__getinitargs__ = a

    print str(obj)

これで、インスタンスの選択が解除され、属性がなくなったことがわかりますb

于 2013-01-09T16:07:24.813 に答える
1

カスタム クラスを変更して、オプションで 2 番目のパラメーターを必要とする場合があります。これにより、ピクルされたオブジェクトとの賞の互換性が失われます。

于 2013-01-09T15:24:22.860 に答える