[pickle] Different version of a class

Michael S. Schliephake mss at kepler.de
Mon Jun 7 02:40:32 EDT 1999


Hallo -

> my application uses pickle to store and load data.
> 
> During developing cycle, many variables are added
> to the classes which are pickled. Whenever I load
> a file pickled with a previous version, some
> variables are not existent (naturally, because
> __init__ is not called). Is there an easy way
> to initialize the "new" variables or must I
> call __init__ - which would overwrite some of
> my saved variables.

In the following the method I use for program options an so on.
It's easy to maintain backward compatibility too.

Michael
---

import pickle


class aOptionDict :
  DVersion = 0              # no version traced
  def __init__( self ):
    self.DVersion = self.__class__.DVersion

  def __getinitargs__(self):
    return ()

  def __setstate__(self, dict):
    self.__dict__.update(dict)


"""
# The class in version 1:

class AppOptions (aOptionDict):
  DVersion = 1
  def __init__( self ):
    aOptionDict.__init__(self)
    self.inpData  = 'in Version 1 added'

  def __setstate__( self, dict ):
    # Not so much to do, transfer data into self
    aOptionDict.__setstate__(self, dict)

"""

# The class in version 2:

class AppOptions (aOptionDict):
  DVersion = 2
  def __init__( self ):
    aOptionDict.__init__(self)
    self.inpData  = 'in Version 1 added, in 2 initialized'
    self.newData  = 'in version 2 added'
    self.calcData = ''  # in version 2 added, depends from version 1 too

  def __setstate__( self, dict ):
    if dict['DVersion'] < self.DVersion:
      print 'Preprocessing older object ' , \
                  self.DVersion, ' <- ', dict['DVersion']
      # delete unnecessary elements from dict (but only if no
      # compatibility for backward use will be required).

    # transfer data into self
    aOptionDict.__setstate__(self, dict)

    if self.DVersion < self.__class__.DVersion:
      print 'Postprocessing older object ' , \
                  self.__class__.DVersion, ' <- ', self.DVersion
      # Do some calculations if necessary
      # Default values are already correct
      # (For backward compatibility do not change the semantic
      # of existing class members)
      self.calcData = self.inpData + ' ' + self.newData
      
      # Update the version number
      self.DVersion = self.__class__.DVersion
    

def saveOptions(od):
  fp = open('xxx.txt', 'w')
  pck = pickle.Pickler(fp)
  pck.dump(od)

def readOptions()
  fp = open('xxx.txt', 'r')
  pck = pickle.Unpickler( fp )
  return pck.load()




More information about the Python-list mailing list