34

type()最終的にピクルされるクラスを動的に生成するために使用しています。問題は、ピクルされたオブジェクトを再構築するために、アンピクル プロセスがクラスの定義を必要とすることです。

これは私が立ち往生しているところです。動的に生成されたクラスからインスタンスを生成する方法を unpickler に提供する方法がわかりません。

ヒントをいただければ幸いです。

ありがとう!

問題の例を次に示します。

    >>> class Foo(object):
    ...     pass
    >>> g=type('Goo',(Foo,),{'run':lambda self,x: 2*x } )()
    >>> cPickle.dumps(g)

    PicklingError: Can't pickle <class '__main__.Goo'>: attribute lookup __main__.Goo failed

これは明らかに機能しますが、ピクル可能な基本クラスから作成された動的クラスからのみ (検索可能なモジュール定義を使用):

import cPickle

class Foo(object): pass

def dynamic(): return type('Goo',(Foo,),{'run':lambda self,x: 2*x } )()

g=type('Goo',(Foo,),{'run':lambda self,x: 2*x , '__reduce__': lambda self: (dynamic,tuple()) } )()

gg=cPickle.loads ( cPickle.dumps(g) )
print gg.run(10)
4

6 に答える 6

18

Pickler が何も知らないタイプのオブジェクトに遭遇すると、reduce メソッドを探します。型を使用してカスタム クラスを構築するときにこのメソッドを定義すると、酸洗の問題が解決するはずです。

初期引数を指定する場合、さらにgetnewargs メソッドを定義する必要がある場合があります

于 2012-08-02T03:11:10.590 に答える
5

動的に生成されたクラスにグローバル名を割り当てて、picklable にすることができます。

>>> class Foo(object):
...     pass
>>> class_name = 'Goo'
>>> my_class = type(class_name, (Foo, ), {'run': lambda self, x: 2*x })
>>> globals()[class_name] = my_class
>>> g = my_class()
>>> pickle.dumps(g)

もちろん、クラスの名前が一意であることを確認する必要があります。

于 2016-09-16T10:24:30.217 に答える
2

1 つのアイデアは、タプルを次のようにピクルすることです。

  1. 動的クラスの名前
  2. サブクラスのタプル (おそらく repr() からの文字列形式)
  3. クラス辞書
  4. 実際のインスタンス

これにより、クラスをピクルし、後で type() を使用して再構築し、Unpickler をサブクラス化できます。

于 2012-07-25T21:06:59.393 に答える
1

非動的クラスの場合、python のピクル メカニズムはモジュールとクラス名を文字列として記録します。unpickle 時に、そのモジュールからクラス オブジェクトを自動的にロードします。

元の投稿で述べたように、ここでの問題は、動的クラスの場合、クラス定義自体がデフォルトの pickler によって pickle 化されないことです。動的クラスはモジュールのソース ファイルに存在しないため、動的クラスの unpickle は通常は機能しません。

クラス自体をピクルする最も難しい部分は、メソッドのバイトコードを格納することです。PiCloud に埋もれている内部には拡張された pickler があり、オブジェクトを処理するために使用または拡張できる可能性 のある動的関数を pickle化できます。

于 2012-08-02T12:54:13.650 に答える
0

私は自分でやったことがありませんが、http://docs.python.org/library/pickle.html#subclassing-unpicklersは、サブクラス化することで動作をオーバーライドできることを示しているようですUnpickler

于 2012-07-25T21:04:50.280 に答える