How to unpickle an object whose class exists in a different namespace (python)?

前端 未结 2 1912
清酒与你
清酒与你 2021-01-04 07:26

If I have a script that defines a class:

script = \"\"\"

class myClass:
    def __init__(self):
        self.name = \'apple\'
        self.color = \'green\'         


        
2条回答
  •  醉梦人生
    2021-01-04 07:27

    You can actually go one step further, and have the object reconstruct itself into whatever type you want.

    import pickle
    import copy_reg
    
    class myClass(object):
        def __init__(self):
            self.apple = 'banana'
    
    class otherclass(object):
        def __init__(self):
            self.apple = 'existential woe'
    
    def pickle_an_object(o):
        print "pickling %s" % str(o)
        return otherclass, (o.apple,)
    
    copy_reg.pickle(myClass, pickle_an_object)
    
    foo = myClass()
    
    s = pickle.dumps(foo)
    
    del myClass
    del otherclass
    
    class otherclass(object):
        def __init__(self, appletype):
            self.apple = 'not %s' % appletype
    
    o2 = pickle.loads(s)
    
    print o2.apple
    

    The basic idea is that you pack your class into a "trojan horse" of sorts, where its reconstruction causes an instantiation of a different class from what it originally was.

    It does not matter what the otherclass on the pickling side contains. All that matters is that it exist at the same module path as the "destination" class - pickle is just putting a string representation of the module name into the serialized stream.

    So, to break down what's happening in the above code in detail:

    • We register a custom pickler for myClass. This can be done via copy_reg or the __reduce_ex__ function.
    • Our custom pickler says "pickle this as an instance of otherclass" (which is a dummy. You do not need the "real" contents of otherclass on the pickling side, because all that goes into the pickle is the module/class name).
    • We pickle the object and "send it across the wire", to where the real version of otherclass exists.
    • On the remote side, otherclass is instantiated with the data from the tuple returned by the custom pickling function.

    Python can be pretty powerful!

提交回复
热议问题