开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜