4

動的に生成されたクラスを代替クラスのファクトリとしてピクルしようとしています。次のようなもの:

import sys, pickle

class BC(object):
    pass

C = type("NewClassName", (BC,), {})

pickle.dump(C, sys.stdout)

これにより、次のエラーが発生します。

pickle.PicklingError: Can't pickle <class '__main__.NewClassName'>: it's not found as __main__.NewClassName

動的に生成されたクラスのオブジェクトをピクルするために、__reduce__メソッドを定義できますが、クラス定義に対してのみこれを達成する方法はありますか?

新しいクラスのファクトリとしてのみ必要なので、BC を直接使用したくありません。

4

3 に答える 3

2

次のことを試してください。

C = type("C", (BC,), {})

クラスは、型名と同じ名前のモジュール レベル変数である必要があります。

ただし、このように動的に生成されたクラスをピクルすることはできません (@otus からの回答を参照してください)。


私が考えることができる最善の解決策は、 への引数をピクルし、ピクルtype解除するときにクラスを再度作成することです。

漬物:

import sys, pickle

class BC(object):
    pass

args = ("NewClassName", (BC,), {})
C = type(*args)
C._pickle_args = args

pickle.dump(C._pickle_args, sys.stdout)

解凍:

type_args = pickle.loads("<pickled string">)
C = type(*args)
于 2014-06-23T11:17:05.653 に答える
2

エラーの簡単な回避策は、クラス名を変数名として使用して、それpickleを見つけられるようにすることです。

import sys, pickle

class BC(object):
    pass

NewClassName = type("NewClassName", (BC,), {})

pickle.dump(NewClassName, sys.stdout)

ただし、これはおそらくあなたが望むことを実際には行いません。pickled クラスをロードする場合:

pickle.loads("""c__main__
NewClassName
p0
.""")

再びエラーが発生します:

AttributeError: 'module' object has no attribute 'NewClassName'

クラスを定義していない限り。


ドキュメントに記載されているように:

pickle はクラス インスタンスを透過的に保存および復元できますが、クラス定義はインポート可能であり、オブジェクトが格納されたときと同じモジュールに存在する必要があります。

したがって、オブジェクトが正しいクラスを参照していることを確認するためだけに、新しいクラスを生成するために使用することはできません。


他の回答typeに示されているように、パラメーターをピクルするなどの回避策がありますが、それでも、ピッキングとピッキング解除プロセスの両方のグローバル名前空間でクラスを公開しないと、これらの動的クラスのオブジェクトをピクルすることはできません(つまり、を参照する必要がありますクラス)。__main__.ClassName

したがって、動的クラスのアプローチ全体を再考します。

于 2014-06-23T11:17:31.553 に答える
2

dill動的クラス定義をシリアル化できる を使用できます。その後、回避策は必要なく、やりたいことを正確に行うことができます。

Python 2.7.7 (default, Jun  2 2014, 01:33:50) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>>>
>>> class BC(object):
...   pass
... 
>>> c = type("NewClassName", (BC,), {})
>>> _c = dill.dumps(c)    
>>> c2 = dill.loads(_c)
>>> c2
<class '__main__.NewClassName'>
>>> 

dillここにアクセスしてください: https://github.com/uqfoundation

于 2014-06-28T21:12:35.103 に答える