问题描述
我有一个生成器,使用pygame.surfarray.pixels2d()
将一系列简单的平移效果应用于图像Surface
。
但是,我很快发现,随着循环的循环,Python的内存使用量激增,最终MemoryError
并崩溃。
为了找出原因,我到达了一个简单的循环:
import pygame
testsurf = pygame.Surface((1,1))
while True: # normally, this would be a generator.
testarray = pygame.surfarray.pixels2d(testsurf)
del testarray # only necessary if the Surface is blitted.
无论此代码是在实际环境中运行(显示具有有用图像内容的表面,更新显示,实际应用效果)还是作为测试(运行pixels2d
等),Python的内存使用量都急剧增长(大约4Mb / sec,并且速度很快)直到10Mb / sec,不受其他波动的影响),直到它无法占用更多空间为止。
如果我没有将pygame.surfarray.pixels2d(testsurf)
分配给变量,并且如果我不以任何方式对其进行更改,则不会发生此问题,这意味着在不使用内存的情况下使用函数的唯一方法是调用它照原样,没有任何效果。
这意味着我可以看到它,仅此而已。
即使是简单的值分配pygame.surfarray.pixels2d(testsurf)[0,0] = 0
, pygame.surfarray.pixels2d(testsurf)[0,0] = 0
引起内存问题。
我尝试了许多不同的解决方案:
-
在实际测试中,使用
testarray = pygame.surfarray.array2d(testsurf)
代替pixels2d
视图,然后使用pygame.pixels2d(testsurf)[...] = testarray
将阵列应用回目标表面, -
testarray = pygame.surfarray.pixels2d(testsurf).copy()
更改testarray = pygame.surfarray.pixels2d(testsurf).copy()
并将该数组应用于目标表面, -
使用
pygame.surfarray.pixels2d(testsurf)
代替testarray
,这样testarray
视图分配给变量。 -
在上述每种情况下,添加或删除
del testarray
均无效。
在所有情况下,直到我关闭程序并关闭/重新启动IDLE为止,Python的内存使用量(如报告给Task Manager的信息)实际上一直在不断增长,然后释放内存。 如果循环中止,但外壳没有关闭或重新启动,则内存将继续保留。
我不正确地使用pixels2d
吗?
我需要调用一些函数来触发未发生的垃圾回收吗?
是否所有旧的testarray
对象都保留在某个地方而不是被重新分配或删除(公开或在垃圾回收期间)?
某处某处充满了数组(或其他一些数据,我想),但我不知道在哪里,如何或如何做。
我正在使用Python2
并安装了NumPy
。
== 更新 ==
看起来某处正在保存对视图的引用:
from sys import getrefcount
for n in range(25):
testarray = pygame.surfarray.pixels2d(testsurf)
del testarray
>>> getrefcount(testsurf)
... 27
我还发现从几年前以该问题得到解决的消息结束链接pixels2d
以及pixels3d
,但在这里它是。
我的pygame版本是1.9.2pre
;
当然不是四岁。
== 更新 ==
看起来testarray = numpy.array(testsurf.get_view())
也会创建这些幻像引用,因此surfarray
不一定存在缺陷,但与Surfaces本身有关...
1楼
此内存泄漏已在1.9.1release
版本的Pygame或至少在Python2.7 / Windows版本中得到纠正。
安装此版本,问题将消失。
1.9.2pre
可能是该模块的实验版,从未修复过该错误。
尝试解决此版本中的问题可能会难以想象的困难,因为问题似乎出在Pygame的Surface
模块中(据我所知)实际上在C
。
要对其进行纠正,将需要对surface.pyd
组件进行逆向工程,纠正缺陷,然后重新打包-不用说,除非您是从一开始就写东西,否则要进行的工作不仅仅是向上(向下)分级。到1.9.1release(如果您仔细查看 ,您会发现实际上比1.9.2pre半年或更新 )。
它还解释了版本号末尾的小“ pre”。
**-更新-**
,如果您喜欢这种事情。