Help with Python Classes

smarto1000

New Member
Messages
10
Reaction score
0
Points
0
I am working on a Python program in which I create an instance in one module (Module A), pickle it into a file, and use it in another module (Module B). When it is used in Module B I want it to use the class tree in that module as opposed to the class tree in the module where it was created. However, it continues to use Module A's class hierarchy no matter what I try. Please help!!!
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
The module and class names of the pickled object are placed at the start of the pickled string by the base pickler classes (pickle.Pickler and cPickle.Pickler). Your best bet is probably to subclass Unpickler to take optional module and class names. For pickle.Unpickler, override Unpickler.load_global and Unpickler.load_inst. For cPickle.Unpickler, override Unpickler.find_global. For more info, read the Python docs on picklers (especially "Subclassing Unpicklers") and the source code (picklers.py, cPickle.c).
Code:
class XModuleUnpickler(pickle.Unpickler):
    def __init__(self, file, module=None, klass=None):
        pickle.Unpickler.__init__(self, file)
        self.module=module
        self.klass=klass
    
    dispatch = pickle.Unpickler.dispatch.copy()
    
    def load_global(self):
        module = self.readline()[:-1]
        name = self.readline()[:-1]
        klass = self.find_class(self.module or module, self.klass or name)
        self.append(klass)
    dispatch[pickle.GLOBAL] = load_global
    
    def load_inst(self):
        module = self.readline()[:-1]
        name = self.readline()[:-1]
        klass = self.find_class(self.module or module, self.klass or name)
        self._instantiate(klass, self.marker())
    dispatch[pickle.INST] = load_inst
    
    def find_class(self, module, name):
        if type(name) is str:
            if type(module) is str:
                __import__(module)
            elif type(module) is module:
                mod=module
            else:
                raise TypeError(__name__ + ' argument 1 must be a string or module')
            mod = sys.modules[module]
            klass = getattr(mod, name)
        elif (type(name) is type) or (type(name) is type(self.__class__)):
            klass=name
        else:
            raise TypeError(__name__ + ' argument 2 must be a string or class')
        return klass
Usage:
Code:
# Use class specified in pickled data but change the module
xunpickle = XModuleUnpickler(file, foo)
# Use different module & class, specified by name
xunpickle = XModuleUnpickler(file, 'foo', 'Bar')
# Use different module & class, specified by module and class
xunpickle = XModuleUnpickler(file, foo, Bar)
# Use different class, specified by unqualified class
xunpickle = XModuleUnpickler(file, klass=Bar)
# Use different class, specified by qualified class
xunpickle = XModuleUnpickler(file, klass=foo.Bar)

bar=xunpickle.load()
 
Top