pickle and instancemethod objects

S

Steven Bethard

I'd like to be able to pickle instancemethod objects mainly because I
want to be able to delay a call like ``foo(spam, badger)`` by dumping
``foo``, ``spam`` and ``badger`` to disk and loading them again later.
Sometimes the callable ``foo`` is actually a bound method, e.g.
``bar.baz``, but in such cases, pickle doesn't work by default because
it doesn't know how to pickle/unpickle instancemethod objects.

I was thinking of doing something like::
.... func_name = method.im_func.__name__
.... cls = method.im_class
.... obj = method.im_self
.... return unpickle_instancemethod, (func_name, cls, obj)
........ if obj is None:
.... return getattr(cls, func_name)
.... else:
.... return getattr(obj, func_name)
........ def __init__(self, foo, bar):
.... self.foo = foo
.... self.bar = bar
.... def baz(self):
.... return self.foo, self.bar
........ pickle_instancemethod,
.... unpickle_instancemethod)

This seems to basically do the right thing on the few simple things I've
tried::
('eki', 'fekang')

Does this approach seem sound? Am I going to run into some weird
problems doing it this way?

Thanks,

STeVe
 
?

=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=

Steven said:
Does this approach seem sound? Am I going to run into some weird
problems doing it this way?

It's good, but I think rebuilding the object through
new.instancemethod should be even better.

py> class A:
.... def f(self):print "A"
....
py> class B(A):
.... def f(self):print "B"
....
py> b=B()
py> b.f
<bound method B.f of <__main__.B instance at 0xa7d728cc>>
py> x = new.instancemethod(A.__dict__['f'], b, A)
py> x
<bound method A.f of <__main__.B instance at 0xa7d728cc>>
py> x()
A
py> b.f()
B
py> x.im_func.__name__,x.im_class,x.im_self
('f', <class __main__.A at 0xa7d7002c>, <__main__.B instance at 0xa7d728cc>)

On unpickling x, you'ld get x.(B.f), not x.(A.f) with your
approach.

Not sure it matters much.

Regards,
Martin
 
S

Steven Bethard

Martin said:
Steven said:
Does this approach seem sound? Am I going to run into some weird
problems doing it this way?

It's good, but I think rebuilding the object through
new.instancemethod should be even better.

py> class A:
... def f(self):print "A"
...
py> class B(A):
... def f(self):print "B"
...
py> b=B()
py> b.f
<bound method B.f of <__main__.B instance at 0xa7d728cc>>
py> x = new.instancemethod(A.__dict__['f'], b, A)
py> x
<bound method A.f of <__main__.B instance at 0xa7d728cc>>
py> x()
A
py> b.f()
B
py> x.im_func.__name__,x.im_class,x.im_self
('f', <class __main__.A at 0xa7d7002c>, <__main__.B instance at 0xa7d728cc>)

On unpickling x, you'ld get x.(B.f), not x.(A.f) with your
approach.

Not sure it matters much.

Probably doesn't matter for my particular use, but it certainly wouldn't
hurt to do it the careful way. Thanks.

Is new.instancemethod basically equivalent to calling __get__? That is,
would the following two unpickle_instancemethod functions do the same thing?

def unpickle_instancemethod(func_name, cls, obj):
return cls.__dict__[func_name].__get__(obj, cls)

def unpickle_instancemethod(func_name, cls, obj):
return new.instancemethod(cls.__dict__[func_name], obj, cls)

Thanks again,

STeVe
 

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,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top