1

collections.OrderedDict 標準クラスのサブクラスを作成しました。このクラスのオブジェクトを unpickle しようとすると、次のエラーが発生します。

Traceback (most recent call last):
  File "pickle.py", line 29, in <module>
    print cPickle.load(f)
TypeError: ('__init__() takes exactly 1 argument (2 given)', <class '__main__.ConfiguratorsDict'>, ([['toto', 20]],))

このような動作の理由を理解しようとして、collections.OrderedDict の本体を絞り込んで、次の最小限のコードを取得し、説明済みのエラーをトリガーしました。ここにあります:

import cPickle

class OrderedDict(dict):
    def __reduce__(self):
        items = [[k, self[k]] for k in self]
        inst_dict = vars(self).copy()
        for k in vars(OrderedDict()):
            inst_dict.pop(k, None)
        if inst_dict:
            return (self.__class__, (items,), inst_dict)

        return self.__class__, (items,)

class ConfiguratorsDict(OrderedDict):

    def __init__(self):
        OrderedDict.__init__(self)

        self._myspec = "blabla"

if __name__ == "__main__":

    f = open("test.pickle","wb")
    c = ConfiguratorsDict()
    c["toto"] = 20
    cPickle.dump(c,f)
    f.close()    
    f = open("test.pickle","rb")
    print cPickle.load(f)
    f.close()

この時点で、何がうまくいかないのか本当にわかりません。pickle メカニズムで誤解していることはありますか、それとも OrderedDict に関連する問題がありますか?

助けてくれてどうもありがとう

4

1 に答える 1

3

__reduce__ドキュメントを十分に注意深く読んでいませんでした:

タプルが返される場合、要素の長さは 2 ~ 5 である必要があります。オプションの要素は、省略したりNone、値として指定したりできます。このタプルの内容は、通常どおり pickle 化され、unpickle 時にオブジェクトを再構築するために使用されます。各要素のセマンティクスは次のとおりです。

  • オブジェクトの初期バージョンを作成するために呼び出される呼び出し可能なオブジェクト。タプルの次の要素は、この callable の引数を提供し、後の要素は追加の状態情報を提供します。この情報は、後にピクルされたデータを完全に再構築するために使用されます。

クラスを callable および 2 番目の要素として返しているitemsため、unpickle は をitemsクラスに渡して を呼び出しようとし__init__ています__init__が、引数を取らないため、エラーが発生します。

を変更し__init__て引数を受け入れるか、それを 2 番目の要素として入れないようにし、代わりに空のタプルにする必要があります。

于 2014-03-27T14:45:51.863 に答える