プログラムの正確な状態を保存し、後で再ロードするオプションをユーザーに提供したい pygame で描画プログラムを作成しています。この時点で、グローバル dict のコピーを保存し、すべてのオブジェクトをピクルして繰り返します。pygame にはピクルできないオブジェクトがいくつかありますが、文字列に変換してその方法でピクルすることができます。私のコードはこれを行うように設定されていますが、これらの unpicklable オブジェクトの一部は参照によって到達されています。つまり、それらはグローバル ディクショナリにはありませんが、グローバル ディクショナリ内のオブジェクトによって参照されます。この再帰でそれらをピクルしたいのですが、ピクルに問題があったオブジェクトを返し、変更してから再度ピクルするように指示する方法がわかりません。私のコードは、私がやったことを行うための別の優れた方法がある場合、本当に非常に面倒です.
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