how to pickle unpicklable objects

G

Guy Lateur

Hi all,

I've been writing an application containing a lot of settings which can be
changed by the user. I'm using wx.Config to read/write these settings (to
the windows registry). This means I can only store strings, ints and floats.

However, it would be very convenient if I could also store more general
objects. It seems to work for wx.Colour, but not for wx.Font. It raises a
"TypeError: can't pickle PySwigObject objects".

Does anybody a way to get around this? Is there some other module that would
allow writing general (small) objects to the registry? Some sort of
serialiser or something?

TIA,
g
 
I

Ido.Yehieli

interesting.
usually the [pickle | cpickle | marshal] modules should handle such
things
 
H

Hans Georg Krauthaeuser

Guy said:
Hi all,

I've been writing an application containing a lot of settings which can be
changed by the user. I'm using wx.Config to read/write these settings (to
the windows registry). This means I can only store strings, ints and floats.

However, it would be very convenient if I could also store more general
objects. It seems to work for wx.Colour, but not for wx.Font. It raises a
"TypeError: can't pickle PySwigObject objects".

The object is wrapped by SWIG. So, python can not know anything about it
and the object can not be pickled.

As far as I see, there are two possibilities
- define __getstate__ and __setstate__ in the c/c++-source or the .i
file (used by swig). This is only possible if the source is available
- use copy_reg (http://docs.python.org/lib/module-copyreg.html) to
register a 'reduce' function (I never used that).

I use the first option in the .i-File for a wrapped c++-class like this:

%extend UMDMResult {
%insert("python") %{
def __getstate__(self):
return (self.v,self.u,self.l,self.unit,self.Z0,self.Eta0,self.t)
def __setstate__(self,tup):
self.this = _umddevice.new_UMDMResult(tup[0],tup[1],tup[2],tup[3])
self.thisown=1
(self.Z0,self.Eta0,self.t)=[i for i in tup[4:]]
%}
}

regards
Hans Georg Krauthaeuser
 
G

Guy Lateur

Thanks for the swift reply, Hans, and sorry for my delayed reaction.

I've been looking at the copy_reg module, but I can't seem to get it to
work.

wx.Font has a method called GetNativeFontInfo(), which returns a string
description of the font. Here's what I had hoped would have worked.

Code:
def reducef(objf):
    return str(objf.GetNativeFontInfo())
def constrf(strf):
    rv = wx.Font()
    rv.SetNativeFontInfo(wx.String(strf))
    return rv
copy_reg.pickle(wx.Font, reducef, constrf)
valf = wx.Font(10, wx.NORMAL, wx.NORMAL, wx.NORMAL, False, 'Arial')
rvf = pickle.dumps(valf)

Unfortunately, this raises the exception:
pickle.PicklingError: Can't pickle <wx._gdi.Font; proxy of C++ wxFont
instance at _c8bb6101_p_wxFont>: it's not found as
wx._gdi.0;-13;0;0;0;400;0;0;0;1;0;0;0;32;Arial

Like I said, this is how I hoped it would work. I've read in the pickle docs
you should return the name of a global var containing the value to be
pickled as usual. I've tried this (without really understanding it), too,
but without any success.

Could somebody please help me to modify this example so that it works?

Best regards,
g




Hans Georg Krauthaeuser said:
Guy said:
Hi all,

I've been writing an application containing a lot of settings which can
be
changed by the user. I'm using wx.Config to read/write these settings (to
the windows registry). This means I can only store strings, ints and
floats.

However, it would be very convenient if I could also store more general
objects. It seems to work for wx.Colour, but not for wx.Font. It raises a
"TypeError: can't pickle PySwigObject objects".

The object is wrapped by SWIG. So, python can not know anything about it
and the object can not be pickled.

As far as I see, there are two possibilities
- define __getstate__ and __setstate__ in the c/c++-source or the .i
file (used by swig). This is only possible if the source is available
- use copy_reg (http://docs.python.org/lib/module-copyreg.html) to
register a 'reduce' function (I never used that).

I use the first option in the .i-File for a wrapped c++-class like this:

%extend UMDMResult {
%insert("python") %{
def __getstate__(self):
return (self.v,self.u,self.l,self.unit,self.Z0,self.Eta0,self.t)
def __setstate__(self,tup):
self.this = _umddevice.new_UMDMResult(tup[0],tup[1],tup[2],tup[3])
self.thisown=1
(self.Z0,self.Eta0,self.t)=[i for i in tup[4:]]
%}
}

regards
Hans Georg Krauthaeuser
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top