我有一個生成器,它將一系列簡單的翻譯效果應用於圖像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