Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I change the definition of class methods after pickling

I am writing a class that does some data processing. I initiated the class and did some processing then pickled the results. the problem is that I added new methods to the class and loaded the pickled objects but I couldn't apply the new methods to the unpickled ones.

For example, This is my class

class Play(ABC):
  def __init__(self, data):
    self.data = data
    
  @abstractmethod
  def method(self):
    pass

class M(Play):

  def __init__(self, data):
    super().__init__(data)

  def method(self):
    self.corr = np.corrcoef(self.data)

I did some processing

mat = np.random.rand(102, 641)
s = M(mat)
s.method()

and pickled them using dill

def save_object(obj, filename):
    with open(filename, 'wb') as output:  
        dill.dump(obj, output, dill.HIGHEST_PROTOCOL)
save_object(s, 'file.pkl')  

then, I added new methods to the class and unpickled the file to apply those methods but I couldn't

class Play(ABC):
  def __init__(self, data):
    self.data = data
    
  @abstractmethod
  def method(self):
    pass

class M(Play):

  def __init__(self, data):
    super().__init__(data)

  def method(self):
    self.corr = np.corrcoef(self.data)
  
  def new(self):
    # pass
    self.q = self.corr.shape
def load_object(filename):
  with open(filename, 'rb') as input:
    obj = dill.load(input)
    return obj
obj = load_object('file.pkl')
obj.new()

and I get this result

AttributeError: 'M' object has no attribute 'new'

How can I fix that?

like image 299
Ahmed Avatar asked Dec 16 '25 13:12

Ahmed


1 Answers

I'm the dill author. You may want to look at the different pickling settings (see dill.settings). For example:

>>> class Foo(object):
...   x = 1
...   def bar(self, y):
...     return y + self.x
... 
>>> import dill
>>> f = Foo()
>>> s = dill.dumps(f)
>>> f.bar(5)
6
>>> 
>>> class Foo(object):
...   x = 10
...   def bar(self, y):
...     return y + self.x**2
... 
>>> g = dill.loads(s)
>>> g.bar(5)
105
>>> g = dill.loads(s, ignore=True)
>>> g.bar(5)
6
>>> dill.settings
{'protocol': 4, 'byref': False, 'fmode': 0, 'recurse': False, 'ignore': False}
>>> 

here, ignore=True on load tells dill to ignore an existing class definition if a newer one exists. The other settings are to be used on dump/dumps, where for example, byref=True tells dill to not store the class definition at all -- just use whatever references is available in the unpicking environment.

like image 149
Mike McKerns Avatar answered Dec 19 '25 02:12

Mike McKerns



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!