【问题标题】:Python: Save dynamically created object typesPython:保存动态创建的对象类型
【发布时间】:2011-07-17 23:45:38
【问题描述】:

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

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

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

【问题讨论】:

    标签: python django class types


    【解决方案1】:

    在 python 中,类也是对象。因此,您应该能够腌制类对象,并将它们保存到文件中。然后你可以稍后解开它们。

    【讨论】:

    • 您的回答不适用于动态创建的类型。我正在尝试创建动态 django 表单,当我尝试保存表单 Can't pickle <class 'django.forms.forms.DynamicForm'>: it's not found as django.forms.forms.DynamicForm 时出现此错误
    【解决方案2】:

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

    “json 模块提供了一个类似于 pickle 的 API,用于将内存中的 Python 对象转换为称为 JavaScript 对象表示法 (JSON) 的序列化表示。与 pickle 不同,JSON 具有在多种语言(尤其是 JavaScript)中实现的好处,使其适用于应用程序间通信。JSON 可能最广泛用于 AJAX 应用程序中的 Web 服务器和客户端之间的通信,但不限于该问题域。(...)"

    JSON Module at 'Python Module of The Week' website

    【讨论】:

    • AFAIK,JSON 模块要求您事先知道对象类型并明确告诉它如何处理该类型。
    【解决方案3】:

    您不能腌制课程,即使您解决了“...未找到为...”的问题,它仍然无法正常工作(如保存课程的名称,没有内容,然后无法unpickle,因为程序重新启动后该类不存在)

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

    【讨论】:

      【解决方案4】:

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

      快速搜索 SO 会发现这篇有用的帖子:getting the class path or name space of a class in python even if it is nested

      【讨论】:

        【解决方案5】:

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

        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
        

        【讨论】:

        • 解酸前还要注入,所以没用。
        【解决方案6】:

        如何创建一个具有创建、pickle 和 unpickle 动态创建类型对象的方法的工厂类?下面是一个粗略的开始。要使用,只需将调用 pickle.dump(type, fh) 替换为 TypeFactory.pickle(type, fh),并将调用 pickle.load(fh) 替换为 TypeFactory.unpickle(fh)。

        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)
        

        【讨论】:

        • 我应该将什么cls 参数传递给unpickle,因为我不太可能事先知道pickled 类的定义。
        • Unpickling 可以使用 TypeFactory.unpickle(fh) 完成,其中 cls 隐式提供给 unpickle() 方法,因为它被定义为 @classmethod。现在将这个细节添加到答案中。
        【解决方案7】:

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

        【讨论】:

          猜你喜欢
          • 2019-10-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-08-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-02-19
          相关资源
          最近更新 更多