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