By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
444,089 Members | 2,432 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 444,089 IT Pros & Developers. It's quick & easy.

Help with saving and restoring program state

P: n/a
Hello list...

I'm developing an adventure game in Python (which of course is lots of
fun). One of the features is the ability to save games and restore the
saves later. I'm using the pickle module to implement this. Capturing
current program state and neatly replacing it later is proving to be
trickier than I first imagined, so I'm here to ask for a little
direction from wiser minds than mine!

When my program initializes, each game object is stored in two places
-- the defining module, and in a list in another module. The following
example is not from my actual code, but what happens is the same.

(code contained in "globalstate" module)
all_fruit = []

(code contained in "world" module)
class Apple(object): # the class hierarchy goes back to object, anyway
def __init__(self):
self.foo = 23
self.bar = "something"
globalstate.all_fruit.append(self)
apple = Apple()

I enjoy the convenience of being able to refer to the same apple
instance through world.apple or globalstate.all_fruit, the latter
coming into play when I write for loops and so on. When I update the
instance attributes in one place, the changes are reflected in the
other place. But now comes the save and restore game functions, which
again are simplified from my real code:

(code contained in "saveload" module)
import pickle
import world
def savegame(path_to_name):
world_data = {}
for attr, value in world.__dict__.items():
# actual code is selective about which attributes
# from world it takes -- I'm just keeping this
# example simple
world_data[attr] = value
fp = open(path_to_name, "w")
pickle.dump(world_data, fp)
fp.close()

def loadgame(path_to_name):
fp = open(path_to_name, "r")
world_data = pickle.load(fp)
for attr, value in world_data.items():
setattr(world, attr, value)
fp.close()

The problem is that the game objects only get overwritten in the world
module. The instances in the globalstate.all_fruit list remain
unchanged, which is not the behaviour I want. I started to write code
to get around this. I figured that with each loadgame call, I could
reset all the lists in globalstate to empty, then reappend each game
object to the appropriate list. But this possibility got complicated
fast, because all game objects belong to more than one list. My apple
instance alone would belong to globalstate.all_things,
globalstate.all_fruit, globalstate.all_items, and perhaps others. Some
of the game objects contained in these lists don't need to be a part
of capturing program state in the first place! But I'm stuck, because
unpickling (so far as I understand it) creates a brand new instance
that doesn't know it used to have references to itself in the
globalstate lists.

Any advice out there? I'm looking for a clean, elegant way to
overwrite the same class instance in two arbitrary places at once.
Perhaps the example code I've provided isn't even the best way of
saving and restoring program state. Perhaps I can easily update my
globalstate lists and I'm just overlooking the simple way. Or perhaps
the solution lies in abandoning the concepts of referencing my game
objects through module attributes and lists. I'm open to any
suggestions.

Thanks in advance for any help!

Jacob
Jul 18 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
Take a look at Zope. The ZODB is a highly optimized object
database that handles the pickling, loading, saving, etc. of
Python objects for restoring program state. A ZODB beginner's
tutorial is available here:

http://www.h7.dion.ne.jp/~harm/ZODB-Tutorial.py

Other info at:

http://zope.org/Members/adytumsoluti...LoveZODB_PartI
http://zope.org

Hope information helps.

Larry Bates
Jacob H wrote:
Hello list...

I'm developing an adventure game in Python (which of course is lots of
fun). One of the features is the ability to save games and restore the
saves later. I'm using the pickle module to implement this. Capturing
current program state and neatly replacing it later is proving to be
trickier than I first imagined, so I'm here to ask for a little
direction from wiser minds than mine!

When my program initializes, each game object is stored in two places
-- the defining module, and in a list in another module. The following
example is not from my actual code, but what happens is the same.

(code contained in "globalstate" module)
all_fruit = []

(code contained in "world" module)
class Apple(object): # the class hierarchy goes back to object, anyway
def __init__(self):
self.foo = 23
self.bar = "something"
globalstate.all_fruit.append(self)
apple = Apple()

I enjoy the convenience of being able to refer to the same apple
instance through world.apple or globalstate.all_fruit, the latter
coming into play when I write for loops and so on. When I update the
instance attributes in one place, the changes are reflected in the
other place. But now comes the save and restore game functions, which
again are simplified from my real code:

(code contained in "saveload" module)
import pickle
import world
def savegame(path_to_name):
world_data = {}
for attr, value in world.__dict__.items():
# actual code is selective about which attributes
# from world it takes -- I'm just keeping this
# example simple
world_data[attr] = value
fp = open(path_to_name, "w")
pickle.dump(world_data, fp)
fp.close()

def loadgame(path_to_name):
fp = open(path_to_name, "r")
world_data = pickle.load(fp)
for attr, value in world_data.items():
setattr(world, attr, value)
fp.close()

The problem is that the game objects only get overwritten in the world
module. The instances in the globalstate.all_fruit list remain
unchanged, which is not the behaviour I want. I started to write code
to get around this. I figured that with each loadgame call, I could
reset all the lists in globalstate to empty, then reappend each game
object to the appropriate list. But this possibility got complicated
fast, because all game objects belong to more than one list. My apple
instance alone would belong to globalstate.all_things,
globalstate.all_fruit, globalstate.all_items, and perhaps others. Some
of the game objects contained in these lists don't need to be a part
of capturing program state in the first place! But I'm stuck, because
unpickling (so far as I understand it) creates a brand new instance
that doesn't know it used to have references to itself in the
globalstate lists.

Any advice out there? I'm looking for a clean, elegant way to
overwrite the same class instance in two arbitrary places at once.
Perhaps the example code I've provided isn't even the best way of
saving and restoring program state. Perhaps I can easily update my
globalstate lists and I'm just overlooking the simple way. Or perhaps
the solution lies in abandoning the concepts of referencing my game
objects through module attributes and lists. I'm open to any
suggestions.

Thanks in advance for any help!

Jacob

Jul 18 '05 #2

P: n/a

"Jacob H" <ja********@postmark.net> wrote in message
news:85*************************@posting.google.co m...
I'm developing an adventure game in Python


Since you are not the first, have you looked at what others have done to
save/restore? The Pygame site has code you can look at for adventure (I
believe) and other game types (I know).

Terry J. Reedy

Jul 18 '05 #3

P: n/a
Jacob H wrote:
Hello list...

I'm developing an adventure game in Python (which of course is lots of
fun). One of the features is the ability to save games and restore the
saves later. I'm using the pickle module to implement this. Capturing
current program state and neatly replacing it later is proving to be
trickier than I first imagined, so I'm here to ask for a little
direction from wiser minds than mine!

When my program initializes, each game object is stored in two places
-- the defining module, and in a list in another module. The following
example is not from my actual code, but what happens is the same.

(code contained in "globalstate" module)
all_fruit = []

(code contained in "world" module)
class Apple(object): # the class hierarchy goes back to object, anyway
def __init__(self):
self.foo = 23
self.bar = "something"
globalstate.all_fruit.append(self)
apple = Apple()

I enjoy the convenience of being able to refer to the same apple
instance through world.apple or globalstate.all_fruit, the latter
coming into play when I write for loops and so on. When I update the
instance attributes in one place, the changes are reflected in the
other place. But now comes the save and restore game functions, which
again are simplified from my real code:
My understanding of pickle is that it will correctly handle shared references in the saved data. So
if you pack all your global dicts into one list and pickle that list, you will get what you want.
See code changes below:

(code contained in "saveload" module)
import pickle
import world import globalstate def savegame(path_to_name):
world_data = {}
for attr, value in world.__dict__.items():
# actual code is selective about which attributes
# from world it takes -- I'm just keeping this
# example simple
world_data[attr] = value the_whole_shebang = [ world_data, globalstate.all_fruit, globalstate.all_items ] fp = open(path_to_name, "w") pickle.dump(the_whole_shebang, fp) fp.close()

def loadgame(path_to_name):
fp = open(path_to_name, "r") the_whole_shebang = pickle.load(fp)
world_data, globalstate.all_fruit, globalstate.all_items = the_whole_shebang for attr, value in world_data.items():
setattr(world, attr, value)
fp.close()


Kent
Jul 18 '05 #4

P: n/a
Jacob H wrote:
Hello list...

I'm developing an adventure game in Python (which of course is lots of fun).
I am glad you are having fun ,
after all life is so short,
isn't that what it is all about ;)
One of the features is the ability to save games and restore the
saves later. I'm using the pickle module to implement this. Capturing
current program state and neatly replacing it later is proving to be
trickier than I first imagined, so I'm here to ask for a little
direction from wiser minds than mine!

When my program initializes, each game object is stored in two places
-- the defining module, and in a list in another module. The following example is not from my actual code, but what happens is the same.

(code contained in "globalstate" module)
all_fruit = []

(code contained in "world" module)
class Apple(object): # the class hierarchy goes back to object, anyway def __init__(self):
self.foo = 23
self.bar = "something"
globalstate.all_fruit.append(self)
apple = Apple()

[snip]
Ok here is a guess. (I recently did something similar, maybe this will
help)
If you already knew about this stuff then just ignore me :)

You have defined a class for your objects, which is a nifty
'container'.
The apple class can also keep track of the total amount of apple
instances handed out.
Sometimes it is better to let the objects handle there own state.
Py> class Apple(object):
.... total = 0 # this is a 'class variable' shared by all instances

.... def __init__(self):
.... self.__class__.total += 1
.... self.foo = 23 # this is an 'instance variable/name'
.... self.bar = "something"
.... apple = Apple()
.... apple_two = Apple()
.... print apple_two.total
.... 2
.... apple_three = Apple()
.... print apple.total
.... 3
.... print apple_three.total
.... 3
Now you can just pickle them and when you unpickle them as usual.

Also another idea is to use a class instead of a global.
I'll admit it I have a personal distaste for them, but classes work so
well I never miss them.

Py>class Store(object):
.... pass

Now just create an instance and add your attributes.
Py>store = Store()
....store.color = 'red'
....store.height = 5.7
....store.secret = 42
And get them back when needed.
Py>self.SetHieght(store.hieght)

Hth
M.E.Farmer

Jul 18 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.