[C++-sig] Pickle python subclass of C++ interface

John Reid j.reid at mail.cryst.bbk.ac.uk
Sun Jul 18 17:09:40 CEST 2010


John Reid wrote:
> 
> 
> Ralf W. Grosse-Kunstleve wrote:
>>> Ok I'll give that a whirl. I was hoping to avoid doing __getinitargs__()
>>> for each subclass as I have quite a few of them. If I didn't have a C++
>>> base class then the pickling would just work as is. There's no way I
>>> can get back to that sort of situation with the C++ base class is there?
>>
>> I don't know, but there may be. One (totally untested) idea would be to
>> give the base class __getstate__ and __setstate__ methods that inspect 
>> the
>> instance to re/store the state. Maybe you just need to return and restore
>> self.__dict__?
>> I guess you could mix-in the __getstate__, __setstate__ methods.
>>
>> Ralf
> 
> 
> I'm not sure what you mean by mix-in, but my first attempt involved 
> defining pickle suite getstate() and setstate() methods. I did not 
> define a getinitargs() method. Unfortunately when the derived object was 
> unpickled, __init__ was called with no arguments. As far as I can see 
> there's no way to use the boost.python pickle suite that does not 
> involve a call to __init__() on the unpickled object.
> 
> I'll try having a go using the python pickling protocol's __reduce__() 
> method.

Ok this seems to work by injecting a __reduce__() method into the C++ 
base class. Here ext is the extension module and A is the C++ base class:


import ext, cPickle, logging, copy_reg

def __newobj__(cls, *args):
     return cls.__new__(cls, *args)

def __reduce__(self):
     return (
         __newobj__,
         (self.__class__,),
         self.__dict__
     )
ext.A.__reduce__ = __reduce__

class Derived(ext.A):
     def __init__(self, init_arg):
         self.data = init_arg

derived = Derived(1)
pickled_repr = cPickle.dumps(derived)
unpickled = cPickle.loads(pickled_repr)
assert unpickled.data == derived.data



John.



More information about the Cplusplus-sig mailing list