Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Pickle derived classes as if they were an instance of the base class

I want to define a base class so that when derived class instances are pickled, they are pickled as if they are instances of the base class. This is because the derived classes may exist on the client side of the pickling but not on the server side, but this is not important to the server since it only needs information from the base class. I don't want to have to dynamically create classes for every client.

The base class is simply an "object handle" which contains an ID, with methods defined on the server, but I would like the client to be able to subclass the server classes and define new methods (which would only be seen by the client, but that doesn't matter).

like image 892
Luke McCarthy Avatar asked Dec 21 '10 15:12

Luke McCarthy


People also ask

Can you pickle a class instance Python?

Instances of any class can be pickled, as will be illustrated in a later example. By default, the pickle will be written in a binary format most compatible when sharing between Python 3 programs.

Why pickle is not good in Python?

Pickle on the other hand is slow, insecure, and can be only parsed in Python. The only real advantage to pickle is that it can serialize arbitrary Python objects, whereas both JSON and MessagePack have limits on the type of data they can write out.

How can I dynamically create derived classes from a base class?

Classes can be dynamically created using the type() function in Python. The type() function is used to return the type of the object. The above syntax returns the type of object.

What is the purpose of pickle in Python?

Pickle in Python is primarily used in serializing and deserializing a Python object structure. In other words, it's the process of converting a Python object into a byte stream to store it in a file/database, maintain program state across sessions, or transport data over the network.


2 Answers

I believe you can do it by giving the object a __reduce__ method, returning a tuple, the first part of which should be BaseClass.__new__ (this will be called when loading the object in unpickling). See the pickle documentation (Python 2, Python 3) for the full details. I haven't attempted this.

Depending on what you're doing, it might be easier to use a simpler serialisation format like JSON, and have code on each side to reconstruct the relevant objects.

like image 69
Thomas K Avatar answered Nov 15 '22 12:11

Thomas K


You can change an object's class dynamically in Python:

import cPickle as pickle

class Foo(object):
    def __init__(self):
        self.id=1
class Bar(Foo):
    def derived_class_method(self): pass

bar=Bar()
bar.id=2
bar.__class__=Foo                # changes `bar`'s class to Foo
bar_pickled=pickle.dumps(bar)
bar2=pickle.loads(bar_pickled)
bar.__class__=Bar                # reset `bar`'s class to Bar
print(repr(bar2))
# <__main__.Foo object at 0xb76b08ec>
print(bar2.id)
# 2

I'm not sure using this is the best design decision, however. I like Thomas K's idea of using JSON.

like image 31
unutbu Avatar answered Nov 15 '22 12:11

unutbu