Python:保存动态创建的对象类型

Python:保存动态创建的对象类型,python,django,class,types,Python,Django,Class,Types,我正在使用type函数动态创建一些对象类型。前 return type('DynamicType', (object,), dict) dict取决于用户输入。现在我想我应该能够保存这个返回的类类型,并在不同的会话中使用相同的类类型。一种可能的方法是将dict保存为文本(或保存到数据库中),然后再次从该dict创建此对象类型。但是有没有其他方法可以直接保存“类型”呢?在python中,类也是对象。因此,您应该能够pickle类对象,并将它们保存到文件中。您可以稍后取消勾选它们。也许您可以尝试使

我正在使用type函数动态创建一些对象类型。前

return type('DynamicType', (object,), dict)

dict取决于用户输入。现在我想我应该能够保存这个返回的类类型,并在不同的会话中使用相同的类类型。一种可能的方法是将dict保存为文本(或保存到数据库中),然后再次从该dict创建此对象类型。但是有没有其他方法可以直接保存“类型”呢?

在python中,类也是对象。因此,您应该能够pickle类对象,并将它们保存到文件中。您可以稍后取消勾选它们。

也许您可以尝试使用json模块(注意:我自己没有使用过它,所以我不知道它是否能解决您的问题,这只是一个建议):

“json模块提供了一个类似于pickle的API,用于将内存中的Python对象转换为称为JavaScript对象表示法(json)的序列化表示形式。与pickle不同,json具有多种语言(特别是JavaScript)实现的优点JSON可能最广泛地用于AJAX应用程序中web服务器和客户端之间的通信,但不限于此问题域。(……)


您不能pickle类,即使您解决了“…未找到为…”的问题,它仍然无法工作(如在保存类名称时,没有内容,然后无法取消pickle,因为程序重新启动后该类不存在)


您必须手动序列化dict并在以后从中重构类,这取决于它包含的内容,这也很有趣:函数对象不能被任何东西序列化,您必须提取它们的代码对象,使用封送序列化它们,然后在加载时重新创建它们。

将dict保存到JSON似乎是最简单的,但是看起来可以利用pickle或shelve创建某种动态类序列化


在SO上快速搜索可以发现以下有用的帖子:

您可以在pickle之前在全局命名空间中“注入”新类,以避免pickle错误:

import pickle

class TestClass(object):
    def __init__(self):
        self.a = 1     # Initial instance attributes
        self.b = 2
        self.c = 3

my_classname = "NewTestClass"
obj = type(my_classname, (TestClass,), {})()
obj.d = 4                # Extra attributes
print obj.a, obj.b, obj.c, obj.d
print obj.__class__

globals()[my_classname] = obj.__class__     # Inject the new class in the global namespace

obj2 = pickle.dumps(obj)
obj = None           # Free original obj instance
obj = pickle.loads(obj2)
print obj.a, obj.b, obj.c, obj.d   # 1,2,3,4

使用创建、pickle和取消pickle动态创建的类型对象的方法创建一个工厂类怎么样?以下是一个艰难的开始。要使用,只需将对pickle.dump(type,fh)的调用替换为TypeFactory.pickle(type,fh),并将对pickle.load(fh)的调用替换为TypeFactory.unpickle(fh)


你的问题没有自动解决的办法。所有“默认”机制(如pickle)都只保存实例数据(包括类型等元数据)。你要做的,就是拯救这个班级。您可能能够使用字节码魔法构建某些东西,但实现自己的序列化代码可能更容易。

您的答案不适用于动态创建的类型。我正在尝试创建动态django表单,当我尝试为表单保存时出现此错误
无法pickle:找不到django.forms.forms.DynamicForm
您还必须在取消pickle之前注入它,因此它没有用。我应该向取消pickle传递什么
cls
参数,因为我不太可能事先知道pickle类的定义。可以使用TypeFactory.unpickle(fh)来完成取消pickle,其中cls隐式地提供给unpickle()方法,因为它被定义为@classmethod。将该细节添加到answer now.AFAIK中,JSON模块要求您事先知道对象类型,并明确告诉它如何处理该类型。
import pickle

class TypeFactory(object):
    def __init__(self):
        pass
    @staticmethod
    def create_type(name='DynamicType', dict={}):
        return type(name, (object,), dict)
    @staticmethod
    def pickle(t, fh):
        dict = t.__dict__.copy()
        name = t.__name__
        for key in dict.keys():
            if key.startswith('__') and key.endswith('__'):
                del dict[key]
        pickle.dump((name, dict), fh)
    @classmethod
    def unpickle(cls, fh):
        name, dict = pickle.load(fh)
        return cls.create_type(name, dict)