我试图挑选pygame.Surface
对象,默认情况下这不是pickleable。我所做的是将经典的可挑选性函数添加到类中并覆盖它。这样它将与我的其余代码一起使用。
class TemporarySurface(pygame.Surface):
def __getstate__(self):
print '__getstate__ executed'
return (pygame.image.tostring(self,IMAGE_TO_STRING_FORMAT),self.get_size())
def __setstate__(self,state):
print '__setstate__ executed'
tempsurf = pygame.image.frombuffer(state[0],state[1],IMAGE_TO_STRING_FORMAT)
pygame.Surface.__init__(self,tempsurf)
pygame.Surface = TemporarySurface
以下是我尝试挑选一些递归对象时的回溯示例:
Traceback (most recent call last):
File "dibujar.py", line 981, in save_project
pickler.dump((key,value))
File "/usr/lib/python2.7/pickle.py", line 224, in dump
self.save(obj)
File "/usr/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/usr/lib/python2.7/pickle.py", line 562, in save_tuple
save(element)
File "/usr/lib/python2.7/pickle.py", line 306, in save
rv = reduce(self.proto)
File "/usr/lib/python2.7/copy_reg.py", line 71, in _reduce_ex
state = base(self)
ValueError: size needs to be (int width, int height)
困扰我的部分是print语句没有被执行。 __getstate__
甚至被调用了吗?我在这里很困惑,我不确定要提供什么信息。如果有任何其他信息可以帮助我,请告诉我。
答案 0 :(得分:3)
作为the documentation says,pickling扩展类型的主要入口点是__reduce__
或__reduce_ex__
方法。鉴于错误,似乎默认的__reduce__
实现与pygame.Surface
的构造函数不兼容。
因此,您最好为__reduce__
提供Surface
方法,或通过copy_reg
模块在外部注册一个方法。我会建议后者,因为它不涉及猴子修补。你可能想要这样的东西:
import copy_reg
def pickle_surface(surface):
return construct_surface, (pygame.image.tostring(surface, IMAGE_TO_STRING_FORMAT), surface.get_size())
def construct_surface(data, size):
return pygame.image.frombuffer(data, size, IMAGE_TO_STRING_FORMAT)
construct_surface.__safe_for_unpickling__ = True
copy_reg.pickle(pygame.Surface, pickle_surface)
这应该就是你所需要的。确保模块顶层的construct_surface
函数可用:unpickling进程需要能够找到函数以执行unpickling过程(可能在不同的解释器实例中发生)