Skip to content Skip to sidebar Skip to footer

How To Remove Instancemethod Objects, For The Sake Of Pickle, Without Modifying The Original Class

I want to persistantly hold on to an object from reverend.thomas.Bayes. Of course, if I try to pickle one of these classes directly, I get: TypeError: can't pickle instancemethod o

Solution 1:

The better solution would be for you to add a __getstate__ method onto the Bayes class (with accompanying __setstate__):

import types
from reverend.thomas import Bayes

defBayes__getstate__(self):
    state = {}
    for attr, value in self.__dict__.iteritems():
        ifnotisinstance(value, types.MethodType):
            state[attr] = value
        elif attr == 'combiner'and value.__name__ == 'robinson':
            # by default, self.combiner is set to self.robinson
            state['combiner'] = Nonereturn state

defBayes__setstate__(self, state):
    self.__dict__.update(state)
    # support the default combiner (an instance method):if'combiner'in state and state['combiner'] isNone:
        self.combiner = self.robinson

Bayes.__getstate__ = Bayes__getstate__
Bayes.__setstate__ = Bayes__setstate__

Now the Bayes class can always be pickled and unpickled without additional processing.

I do see that the class has a self.cache = {} mapping; perhaps that should be excluded when pickling? Ignore it in __getstate__ and call self.buildCache() in __setstate__ if that is the case.

Solution 2:

k is a key i.e. the attribute/method name. You need to test the attribute itself:

iftype(dic[k]) == types.MethodType:
            ^~~~~~ here

I'd prefer using a comprehension; you should also be using isinstance:

dic = dict((k, v) for k, v in bayes_obj.__dict__
           ifnotisinstance(v, types.MethodType))

Solution 3:

This sounds like getting a square peg to fit a round hole. How about using pickle to pickle the arguments, and unpickle to reconstruct the reverand.Thomas.Bayes object?

>>>from collections import namedtuple>>>ArgList = namedtuple('your', 'arguments', 'for', 'the', 'reverand')>>>defpickle_rtb(n):...return pickle.dumps(ArgList(*n.args))...>>>defunpickle_rtb(s):...return reverand.Thomas.Bayes(*pickle.loads(s))...>>>s = pickle_rtb(reverand.Thomas.Bayes(1, 2, 3, 4, 5)) # note arguments are a guess>>>rtb = unpickle_norm(s)

Inspired by this SO question.

Post a Comment for "How To Remove Instancemethod Objects, For The Sake Of Pickle, Without Modifying The Original Class"