Python: Save dynamically created object types
I'm creating some object type开发者_运维问答s dynamically using type function. Ex
return type('DynamicType', (object,), dict)
The dict depends on user input. Now I want that I should be able to save this returned class type and use the same one over different sessions. One possible method is to save the dict as text(or into database) and creating this object type again from that dict. But is there any other way in which I can save the "type" directly?
How about creating a Factory class with methods to create, pickle, and unpickle dynamically created type objects? The following is a rough start. To use, simply replace calls to pickle.dump(type, fh) with TypeFactory.pickle(type, fh), and replace calls to pickle.load(fh) with 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)
You can't pickle classes, even if you solve your "... not found as ..." problem it still won't work (as in save the name of the class, without the content, then fail to unpickle because the class doesn't exist after your program restarts)
You will have to manually serialize dict and reconstruct the class from it later on, which depending on what it contains will be fun too: function objects can't be serialized by anything, you have to extract their code objects, serialize them with marshal then recreate them when loading.
In python, classes are objects too. So, you should be able to pickle the class objects, and save them to a file. You can then unpickle them later.
Maybe you could try json module (note: I haven't used it myself so I don't know if it'll solve your problem, it's just a suggestion):
"The json module provides an API similar to pickle for converting in-memory Python objects to a serialized representation known as JavaScript Object Notation (JSON). Unlike pickle, JSON has the benefit of having implementations in many languages (especially JavaScript), making it suitable for inter-application communication. JSON is probably most widely used for communicating between the web server and client in an AJAX application, but is not limited to that problem domain.(...)"
JSON Module at 'Python Module of The Week' website
Saving the dict to JSON seems like it would be easiest, however it looks like pickle or shelve could be leveraged to create some kind of dynamic class serialization.
A quick search on SO reveals this helpful post: getting the class path or name space of a class in python even if it is nested
You can 'inject' the new class in the global namespace before pickling to avoid the pickle error:
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
There is no automatic solution for your question. All "default" mechanisms, like pickle, just saves the instance data (including metadata like the type). What you want to do, is to save the class too. You might be able to build something using byte code magic, but it's probably easier to implement your own serialization code.
精彩评论