【发布时间】:2011-07-17 23:45:38
【问题描述】:
我正在使用类型函数动态创建一些对象类型。例
return type('DynamicType', (object,), dict)
字典取决于用户输入。现在我希望我应该能够保存这个返回的类类型并在不同的会话中使用相同的类。一种可能的方法是将字典保存为文本(或保存到数据库中)并从该字典再次创建此对象类型。但是有没有其他方法可以直接保存“类型”?
【问题讨论】:
我正在使用类型函数动态创建一些对象类型。例
return type('DynamicType', (object,), dict)
字典取决于用户输入。现在我希望我应该能够保存这个返回的类类型并在不同的会话中使用相同的类。一种可能的方法是将字典保存为文本(或保存到数据库中)并从该字典再次创建此对象类型。但是有没有其他方法可以直接保存“类型”?
【问题讨论】:
在 python 中,类也是对象。因此,您应该能够腌制类对象,并将它们保存到文件中。然后你可以稍后解开它们。
【讨论】:
Can't pickle <class 'django.forms.forms.DynamicForm'>: it's not found as django.forms.forms.DynamicForm 时出现此错误
也许你可以试试 json 模块(注意:我自己没用过所以不知道能不能解决你的问题,只是一个建议):
“json 模块提供了一个类似于 pickle 的 API,用于将内存中的 Python 对象转换为称为 JavaScript 对象表示法 (JSON) 的序列化表示。与 pickle 不同,JSON 具有在多种语言(尤其是 JavaScript)中实现的好处,使其适用于应用程序间通信。JSON 可能最广泛用于 AJAX 应用程序中的 Web 服务器和客户端之间的通信,但不限于该问题域。(...)"
【讨论】:
您不能腌制课程,即使您解决了“...未找到为...”的问题,它仍然无法正常工作(如保存课程的名称,没有内容,然后无法unpickle,因为程序重新启动后该类不存在)
稍后您将不得不手动序列化 dict 并从中重建类,这取决于它包含的内容也会很有趣:函数对象不能被任何东西序列化,您必须提取它们的代码对象,序列化它们marshal 然后在加载时重新创建它们。
【讨论】:
将 dict 保存为 JSON 似乎最简单,但似乎可以利用 pickle 或 shelve 来创建某种动态类序列化。
快速搜索 SO 会发现这篇有用的帖子:getting the class path or name space of a class in python even if it is nested
【讨论】:
您可以在腌制之前在全局命名空间中“注入”新类以避免腌制错误:
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 和 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 类的定义。
您的问题没有自动解决方案。所有“默认”机制,如pickle,只保存实例数据(包括类型等元数据)。你想做的,也是拯救班级。您也许可以使用字节码魔法构建一些东西,但实现您自己的序列化代码可能更容易。
【讨论】: