动态类定义的酸洗 [英] Pickling of dynamic class definition
问题描述
我正在尝试将动态生成的类作为替代类的工厂进行腌制.类似于以下内容:
I am trying to pickle a dynamically generated class as a factory for an alternative class. Something like the following:
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__
方法,但是有没有一种方法可以仅针对类定义来实现这一点.
For pickling an object of a dynamically generated class, you can define an __reduce__
method, but is there a way to achieve this only for a class definition.
我不想直接使用 BC,因为我只需要它作为新类的工厂.
I don't want to use BC directly, because I only need it as a factory for new classes.
推荐答案
该错误的一个简单解决方法是使用类名作为变量名,以便 pickle
可以找到它:
A simple workaround to the error is to use the class name as variable name so that pickle
can find it:
import sys, pickle
class BC(object):
pass
NewClassName = type("NewClassName", (BC,), {})
pickle.dump(NewClassName, sys.stdout)
<小时>
然而,这可能并没有真正做到你想要的.加载pickle类时:
However, this probably doesn't really do what you want. When loading the pickled class:
pickle.loads("""c__main__
NewClassName
p0
.""")
您再次收到错误:
AttributeError: 'module' object has no attribute 'NewClassName'
除非您已经定义了类.
正如文档所述:
pickle 可以透明地保存和恢复类实例,但是类定义必须是可导入的,并且与存储对象时存在于同一模块中.
pickle can save and restore class instances transparently, however the class definition must be importable and live in the same module as when the object was stored.
所以你不能用它来生成新的类,只是为了确保你的对象引用正确的类.
So you can't use it to generate new classes, just to make sure your objects refer to the correct classes.
有一些变通方法,例如酸洗 type
参数,如其他答案所示,但即使那么你将不能在不暴露这些动态类的对象的情况下将类暴露在pickling和unpickling过程的全局命名空间中(即__main__.ClassName
必须引用到班级).
There are workarounds like pickling type
parameters as shown in the other answer, but even then you will not be able to pickle objects of those dynamic classes without exposing the class in the global namespace of both the pickling and the unpickling process (i.e. __main__.ClassName
must refer to the class).
因此,我会重新考虑整个动态类方法.
Therefore, I would rethink the whole dynamic class approach.
这篇关于动态类定义的酸洗的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!