Saving / Restoring data in a program
Bob van der Poel
bvdpoel at kootenay.com
Fri Nov 21 12:39:33 EST 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