I am making a drawing program with pygame in which I want to give the user an option of saving the exact state of the program and then reloading it at a later time. At this point I save a copy of my globals dict and then iterate through, pickling every object. There are some objects in pygame that cannot be pickled, but can be converted into strings and pickled that way. My code is set up to do this, but some of these unpicklable objects are being reached by reference. In other words, they aren't in the global dictionary, but they are referenced by objects in the global dictionary. I want to pickle them in this recursion, but I don't know how to tell pickle to return the object it had trouble with, change it, then try to pickle it again. My code is really very kludge, if there's a different, superior way to do what I'm trying to do, let me know.
surfaceStringHeader = 'PYGAME.SURFACE_CONVERTED:'
imageToStringFormat = 'RGBA'
def save_project(filename=None):
assert filename != None, "Please specify path of project file"
pickler = pickle.Pickler(file(filename,'w'))
for key, value in globals().copy().iteritems():
#There's a bit of a kludge statement here since I don't know how to
#access module type object directly
if type(value) not in [type(sys),type(None)] and \
key not in ['__name__','value','key'] and \
(key,value) not in pygame.__dict__.iteritems() and \
(key,value) not in sys.__dict__.iteritems() and \
(key,value) not in pickle.__dict__.iteritems():
#Perhaps I should add something to the above to reduce redundancy of
#saving the program defaults?
#Refromat unusable objects:
if type(value)==pygame.Surface:
valueString = pygame.image.tostring(value,imageToStringFormat)
widthString = str(value.get_size()[0]).zfill(5)
heightString = str(value.get_size()[1]).zfill(5)
formattedValue = surfaceStringHeader+widthString+heightString+valueString
else:
formattedValue = value
try:
pickler.dump((key,formattedValue))
except Exception as e:
print key+':' + str(e)
def open_project(filename=None):
assert filename != None, "Please specify path to project file"
unpickler = pickle.Unpickler(file(filename,'r'))
haventReachedEOF = False
while haventReachedEOF:
try:
key,value = unpickler.load()
#Rework the unpicklable objects stored
if type(value) == str and value[0:25]==surfaceStringHeader:
value = pygame.image.frombuffer(value[36:],(int(value[26:31]),int(value[31:36])),imageToStringFormat)
sys.modules['__main__'].__setattr__(key,value)
except EOFError:
haventReachedEOF = True