腌制包含 pygame.Surface 个对象的字典

Pickling a dictionary that contains pygame.Surface objects

所以我有一个名为 Images 的字典,它存储 pygame.Surface 个对象。每次我 运行 代码时都不必构建整个字典,我只想从文件中读取它。

这是我试图用来 pickle 和 unpickle 字典的代码:

with open('Images.pkl', 'wb') as output:
    pickle.dump(Images, output, pickle.HIGHEST_PROTOCOL)

with open('Images.pkl', 'rb') as input:
    Images = pickle.load(input)

稍后,我使用此代码:

class Survivor:
    def __init__(self):
        self.body_image=Images['Characters/Survivor/handgun/idle0']
        self.body_rect=self.body_image.get_rect()

这给了我:

File "ZombieSurvival.py", line 1320, in init self.body_rect=self.body_image.get_rect(center=self.vector)
pygame.error: display Surface quit

pygame.Surface 对象实际上是 SDL_Surface 的包装器,它是由 SDL 库处理的 C 结构。必须通过调用 SDL 库的 SDL_CreateRGBSurface() 函数来创建此结构。 这可能是在 pygame.Surface.__init__().

的某处完成的

但是,unpickling 实例不会以正常方式初始化它。正如 pickle documentation 所说:

When a class instance is unpickled, its init() method is usually not invoked

所以 C 结构从未初始化,一切都出错了。

我能够通过首先使用 pygame 的 pygame.image.tostring() 函数将字典 Images 中的每个 pygame.Surface 转换为字符串来腌制字典,使用pygame.image.tostring()。然后我腌制了Images。每当我想使用 Images 时,我都会解开它并使用 pygame.image.fromstring().

将其中的每个字符串转换回 pygame.Surface

然而,pygame.image.fromstring() 要求我们告诉它要转换的 pygame.Surface 的大小,所以我在使用 pygame.Surface 之前保存了每个 pygame.Surface 的大小=22=]函数。

每次我要在 pygame.Surface 上调用 pygame.image.tostring() 时,我首先存储 pygame.Surface 的密钥(它位于 Images 中)并且它在具有字段 keysizeclass 实例中的大小。我将此 class 的每个实例都存储在一个名为 list_of_image_sizes 的列表中,并对该列表进行了腌制。

现在,当您使用 pygame.image.fromstring() 函数时,您可以这样调用它:

for data in list_of_image_sizes:
    Images[data.key]=pygame.image.fromstring(Image[data.key], data.size, 'RGBA')   
    #RGBA is my particular argument, you can change it as you wish