Loading multiple versions of the same package at the same time

Peter Otten __peter__ at web.de
Fri Nov 28 06:08:47 EST 2008


della wrote:

> On 27 Nov, 21:34, Terry Reedy <tjre... at udel.edu> wrote:
> 
>> > But in the interpreters module dict, foo it is, and stays.
>>
>> But giving the modules different names on the disk should work, no?
> 
> Yes, but -- for what I've understood -- that wouldn't solve my
> original problem with pickle, since I would need to carry around a
> module with the new name forever :)

You can rename the globals within the pickle. A starting point, not tested
beyond running the demo script:

$ cat fixpickle.py
import pickle
import pickletools

def ops(d):
    prevpos = None
    previnfo = None
    for info, arg, pos in pickletools.genops(d):
        if prevpos is not None:
            yield d[prevpos:pos]
        prevpos = pos
        previnfo = info
    yield d[prevpos:]


def tocode(dotted):
    parts = tuple(dotted.rsplit(".", 1))
    return "c%s\n%s\n" % parts

def rename_globals(d, pairs):
    updates = dict((tocode(old), tocode(new)) for old, new in pairs)
    return "".join(updates.get(o, o) for o in ops(d))

$ cat alpha.py
class A(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __str__(self):
        return "A(%s, %s)" % (self.x, self.y)

$ cat beta.py
class B(object):
    def __str__(self):
        return "B(%s, %s)" % (self.x, self.y)

$ cat demo.py
import alpha
import fixpickle
import pickle

if __name__ == "__main__":
    a = alpha.A(1, 2)
    print a
    d = pickle.dumps(a)
    d = fixpickle.rename_globals(d, [("alpha.A", "beta.B")])
    b = pickle.loads(d)
    print b

Peter



More information about the Python-list mailing list