Saving / Restoring data in a program

Bob van der Poel bvdpoel at kootenay.com
Fri Nov 21 18:39:33 CET 2003



Lonnie Princehouse wrote:
> It's not entirely clear what you're trying to do, but it sounds like
> you want to save and restore the state of a subset of local namespace.
> 
> First off, rethink this whole scheme.  Consider writing a class for
> your saved data.  Much more Pythonic.

Sorry about being unclear. I tired to make my problem simplier than it 
is, and this probably just led to less clearity. Let me try again...

My progarm, MMA, creates midi accompaniment tracks. (BTW, an alpha 
version of this program is available with demos, docs, etc. on my web 
site.) It lets the user define a "Groove" which is a collection of style 
details. These details include things like the pattern to use for drums, 
piano chords, etc. As well, the groove includes the octave for each 
voice, timing options, volumes, etc.

A user creates a song by listing the chords and setting the grooves. So, 
he might have the first 4 bars of a song with a groove called "SWING", 
the next 8 with "RHUMBA", etc.

What my program needs to do is to save the pattern, etc. in a storage 
space and, when needed, restore the settings from that storage. One 
complication is that the current settings don't need to be saved. So, it 
  isn't as simple as having a pointer to the "SWING" slot. Instead, I 
copy the data from the slot into the current space (overwritting the 
current settings). And all this data from the current space can be saved 
into a storage space.

Now, I do have all this working. I just don't like the way it has been 
implimented. As I tried (poorly) to explain in my previous post, I put 
the various details into storage with code like this... consider the 
variables needed to maintain a piano chord track (this stuff is 
duplicated for drum tracks, etc. And, yes, this is all object based).

Again, trying to make it bit clearer, we have a number of variables. 
I've noted them here with static values, but they are created dynamically.

    self.octave = (4,0,1,5)
    self.timeadjust = (5,5,5,5)
    self.pattern = { vols=(90,80,99,100), start=(0, 25, 50, 75), 
len=(4,4,4,4) }
    ..and a lot more...

Now, at some point we want to save all this so it can be recalled later. 
And, note, we have to save copies of the data, not references. I'm using 
a dict with keys the same as the groove names. So, for the SWING groove, 
the data is saved in self.grooves['SWING']. So, we end up with code:

     self.grooves["SWING"] = {
         'OCTAVE':self.octave[:]
         'TIME':self.timeadjust[:]
         'PATS':self.pattern.copy()
         ... etc }

And, later when we need to restore:

     g=self.grooves["SWING"]
     self.octave=g['OCTAVE']
     self.timeadjust=g['TIME']
     self.pattern=g['PATS']

My concerns with all this are mainly maintainace. Everytime I add or 
modify something I have make sure I add them to the save/restore code. 
And this includes having the right "copy" code (is this a list which can 
be copied with [:], or a dict which needs ".copy", etc). Plus I have to 
make sure I duplicate things properly in the save and restore sections. 
And the spellings of the storage slots ('OCTAVE', 'PATS') has to be the 
same.


> But if you're determined, consider this snippet:

Really not a matter of being determined to do it my way :) But, I am 
determined to keep it working...

> # make some variables
> a = 5
> b = 10
> c = 'foo'
> 
> # Names of variables to save
> save_vars = ['a','b','c']
> 
> # Save them by first dumping their values into a list with
> # a list comprehension
> saved['store1'] = [(key,locals()[key]) for key in save_vars]

If they were all simple items like an integer, then this would be fine. 
But, I have a mix of simple variables, lists and dicts.


> On a side note, it _is_ possible to use pickle without a proper file.
> In your case, it doesn't sound like there's any reason to do this, but
> it does come in handy upon occasion. Pickle only wants something that
> behaves like a file, so you can use a StringIO instead:

Yes, I was thinking of using pickle, but you're right that there doesn't 
seem to be much benefit. But, I will file away the thought of using 
StringIO for a future project. Thanks.

Thinking a bit more about all this it might make the most sense to pack 
all the variables which need saving into a class. What do you think 
about something like this:

   class mutablevariables:
     def __init__(self):
       self.octave = [0,0,0,0]
       self.pats = ...

Now, when I need to reference the octave, I would end up with:

    o = self.mutablevariables.octave[offset]

which isn't that much different from what I'm doing right now which is:

    o = self.octave[offset]

And I can always set a temp variable to make the refs a bit shorts.

And then I can save the whole works with:

     self.grooves["SWING"] = copy.deepcopy(self.mutablevariables)

Is this what you mean by "Consider writing a class for your saved data. 
  Much more Pythonic."

Thanks!

-- 
Bob van der Poel ** Wynndel, British Columbia, CANADA **
EMAIL: bvdpoel at kootenay.com
WWW:   http://www.kootenay.com/~bvdpoel





More information about the Python-list mailing list