How to better pickle an extension type
Ziga Seilnacht
ziga.seilnacht at gmail.com
Tue Apr 17 02:50:27 EDT 2007
dgdev wrote:
> I would like to pickle an extension type (written in pyrex). I have
> it working thus far by defining three methods:
>
> class C:
> # for pickling
> __getstate__(self):
> ... # make 'state_obj'
> return state_obj
>
> __reduce__(self):
> return C,(args,to,__init__),me.__getstate__()
>
> # for unpickling
> __setstate__(self,state_obj):
> self.x=state_obj.x
> ...
>
> This gets the class pickling and unpickling.
>
> However, I'd like to not specify arguments for __init__ (as I do now
> in __reduce__), and so not have __init__ invoked during unpickling.
>
> I would like to have the pickling machinery somehow create an
> uninitialized object, and then call its __setstate__, where I can re-
> create it from 'state_obj'.
>
> Is there a kosher way to do so, that is without me having to have a
> special mode in the constructor for when the object is being created
> by the unpickler?
Why are you overwriting the __reduce__() method? The default
object.__reduce__() method, inherited by all new style classes,
already does what you want. If you really must overwrite it, and
you don't want __init__() to get called, then you should return a
reconstructor named __newobj__() as the first item of reduce
tuple. Something like this:
>>> def __newobj__(cls, *args):
... return cls.__new__(cls, *args)
...
>>> class C(object):
... def __init__(self):
... print "I shouldn't be called at reconstruction"
... def __reduce__(self):
... try:
... getnewargs = self.__getnewargs__
... except AttributeError:
... newargs = (self.__class__,)
... else:
... newargs = (self.__class__,) + getnewargs()
... try:
... getstate = self.__getstate__
... except AttributeError:
... # this ignores __slots__ complications
... state = self.__dict__
... else:
... state = getstate()
... # this ignores list and dict subclasses
... return __newobj__, newargs, state
...
>>> c = C()
I shouldn't be called at reconstruction
>>> import pickle
>>> for proto in range(3):
... assert isinstance(pickle.loads(pickle.dumps(c, proto)), C)
...
>>>
Ziga
More information about the Python-list
mailing list