我有一个生成器,它将一系列简单的翻译效果应用于图像Surface
,使用pygame.surfarray.pixels2d()
。然而,我很快发现,随着循环的循环,Python的内存使用膨胀,最终抛出一个MemoryError
并崩溃。如何防止pygame.surfarray.pixels2d中的内存泄漏?
在试图原因隔离开来,我到达这个简单的循环:
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 /秒,并且快速到10Mb /秒,独立于其他波动),直到它无法占用更多。
如果我没有将pygame.surfarray.pixels2d(testsurf)
分配给变量,并且我没有以任何方式改变它,这意味着使用没有内存使用函数的唯一方法就是不使用气球,而是按原样调用它,没有效果。这意味着我可以看看它,而没有别的。即使是一个简单的值分配,pygame.surfarray.pixels2d(testsurf)[0,0] = 0
,也会导致内存问题。
我已经尝试了许多不同的解决方案:
- 在实际的测试中,使用
testarray = pygame.surfarray.array2d(testsurf)
代替pixels2d
视图,然后使用pygame.pixels2d(testsurf)[...] = testarray
施加阵列回目标表面, - 改变
testarray = pygame.surfarray.pixels2d(testsurf).copy()
并将该阵列应用到目标表面,如上所示, - 使用
pygame.surfarray.pixels2d(testsurf)
代替testarray
,以便视图永远不会分配给变量。 - 在上述每一项中,添加或删除
del testarray
都没有效果。
在所有情况下,Python的内存使用(已报告给任务管理器)的增长实际上是不停,直到我关闭程序和关闭/重新启动IDLE,此时内存被释放。如果循环暂停但外壳未关闭或重新启动,则内存继续保持。
我使用的是不正确的pixels2d
?是否有一些我需要调用的函数触发未发生垃圾回收?所有旧的对象被保存在某个地方而不是被重新分配或删除(公开或在垃圾回收期间)?有些地方正在填满阵列(或者其他一些数据,我想),我不知道在哪里或如何,或者该怎么做。
我正在使用Python2
并安装了NumPy
。
== UPDATE ==
它看起来像到视图一些地方被保存引用:
from sys import getrefcount
for n in range(25):
testarray = pygame.surfarray.pixels2d(testsurf)
del testarray
>>> getrefcount(testsurf)
... 27
我还发现this链接从年前的那一条消息,该问题结束解决了pixels2d
以及pixels3d
,但在这里。我的pygame版本是1.9.2pre
;当然不是四岁。
== UPDATE ==
貌似testarray = numpy.array(testsurf.get_view())
也创建这些虚引用,所以它不一定与surfarray
一个缺陷,但一些与曲面自己做...
如果从命令行运行而不是使用IDLE,它会显示相同的行为吗? – saulspatz
@saulspatz它确实如此。 :C – Augusta