Jeffrey Barish wrote:

> I have a class derived from string that is used in a pickle.  In the new
> version of my program, I moved the module containing the definition of the
> class.  Now the unpickle fails because it doesn't find the module.  I was
> thinking that I could make the unpickle work by putting a copy of the
> module in the original location and then redefine the class by sticking a
> __setstate__ in the class thusly:
> 
> def __setstate__(self, state):
>     self.__dict__.update(state)
>     self.__class__ = NewClassName
> 
> My plan was to specify the new location of the module in NewClassName.
> However, when I do this I get the message "'class' object layout differs
> from 'class'".  I don't think that they do as the new module is a copy of
> the old one.  I suspect that I am not allowed to make the class assignment
> because my class is derived from string.  What is the best way to update
> the pickle?  The only thought I have is to read all the data with the old
> class module, store the data in some nonpickle format, and then, with
> another program, read the nonpickle-format file and rewrite the pickle
> with the class module in the new location.

You could overwrite Unpickler.find_class():

import pickle
from cStringIO import StringIO

class AliasUnpickler(pickle.Unpickler):
    def __init__(self, aliases, *args, **kw):
        pickle.Unpickler.__init__(self, *args, **kw)
        self.aliases = aliases
    def find_class(self, module, name):
        module, name = self.aliases.get((module, name), (module, name))
        return pickle.Unpickler.find_class(self, module, name)

def loads(aliases, str):
    file = StringIO(str)
    return AliasUnpickler(aliases, file).load()

if __name__ == "__main__":
    import before, after
    data = before.A()
    print data.__class__, data
    dump = pickle.dumps(data)
    data = loads({("before", "A"): ("after", "B")}, dump)
    print data.__class__, data

In the example the aliases dictionary maps (module, classname) pairs to
(module, classname) pairs. Of course this only works when the class layout
wasn't changed.

Peter
-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to