我目前正在用 Python 编写一个简单的棋盘游戏,我刚刚意识到垃圾收集不会在重新加载图像时从内存中清除丢弃的位图数据。它仅在游戏启动或加载或分辨率更改时才会发生,但它会增加消耗的内存,所以我不能让这个问题得不到解决。
重新加载图像时,所有引用都将传输到新图像数据,因为它与原始图像数据绑定到的变量相同。我试图通过使用强制垃圾收集,collect()
但它没有帮助。
我写了一个小样本来演示我的问题。
from tkinter import Button, DISABLED, Frame, Label, NORMAL, Tk
from PIL.Image import open
from PIL.ImageTk import PhotoImage
class App(Tk):
def __init__(self):
Tk.__init__(self)
self.text = Label(self, text = "Please check the memory usage. Then push button #1.")
self.text.pack()
self.btn = Button(text = "#1", command = lambda : self.buttonPushed(1))
self.btn.pack()
def buttonPushed(self, n):
"Cycle to open the Tab module n times."
self.btn.configure(state = DISABLED) # disable to prevent paralell cycles
if n == 100:
self.text.configure(text = "Overwriting the bitmap with itself 100 times...\n\nCheck the memory usage!\n\nUI may seem to hang but it will finish soon.")
self.update_idletasks()
for i in range(n): # creates the Tab frame whith the img, destroys it, then recreates them to overwrite the previous Frame and prevous img
b = Tab(self)
b.destroy()
if n == 100:
print(i+1,"percent of processing finished.")
if n == 1:
self.text.configure(text = "Please check the memory usage now.\nMost of the difference is caused by the bitmap opened.\nNow push button #100.")
self.btn.configure(text = "#100", command = lambda : self.buttonPushed(100))
self.btn.configure(state = NORMAL) # starting cycles is enabled again
class Tab(Frame):
"""Creates a frame with a picture in it."""
def __init__(self, master):
Frame.__init__(self, master = master)
self.a = PhotoImage(open("map.png")) # img opened, change this to a valid one to test it
self.b = Label(self, image = self.a)
self.b.pack() # Label with img appears in Frame
self.pack() # Frame appears
if __name__ == '__main__':
a = App()
要运行上面的代码,您需要一个 PNG 图像文件。我的 map.png 的尺寸是 1062×1062。作为 PNG,它是 1.51 MB,作为位图数据,它大约是 3-3.5 MB。使用大图像轻松查看内存泄漏。
运行我的代码时的预期结果:python 的进程一个周期地消耗内存。当它消耗大约 500 MB 时,它会崩溃,但会再次开始消耗内存。
请给我一些建议如何解决这个问题。我很感激每一个帮助。谢谢你。提前。