2015-10-24 42 views
1

我有一个生成器,它将一系列简单的翻译效果应用于图像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一个缺陷,但一些与曲面自己做...

+0

如果从命令行运行而不是使用IDLE,它会显示相同的行为吗? – saulspatz

+0

@saulspatz它确实如此。 :C – Augusta

回答

0

这内存泄漏在Pygame的1.9.1release版本中得到纠正,或者至少是Python2.7/Windows版本。安装此版本,问题就会消失。

1.9.2pre可能是模块的实验版本,从来没有错误修补。在这个版本中尝试和解决问题可能难以想象,因为问题似乎在Pygame的Surface模块中,(据我所知)实际上是C。为了纠正它,它需要对组件进行逆向工程,纠正缺陷,然后重新打包它 - 不用说,除非你先写了这个东西,然后再做更多的工作,而不仅仅是向上(向下)分级到1.9 (如果你仔细观察the files on the Pygame downloads FTP link,你会发现实际上是半年或更多较新的比1.9.2pre)。它还解释了在版本号的末尾有一点点“pre”。

** - 更新 - **

Here's the issue report,如果你喜欢这种东西。

相关问题