内存溢出(?)在 tkinter 上崩溃
Memory overflow(?) crash on tkinter
我正在为自己制作游戏。我遇到的问题是,由于某种原因,程序在将一些对象放在 canvas 上并删除它们后崩溃了。更深入:
我有框架 FrameMain
,里面有一个 canvas。
我有框架 FrameLower
,里面有一个 canvas。还有 canvas.
上的图片
我正在使用 FrameMain.__placeFrames()
方法在 FrameMain
canvas 上放置和删除一些 FrameLower
作为 FrameMain.obj
。
问题是当我删除 FrameMain.obj
时,似乎某处的内存没有完全清除。所以它会导致程序在一段时间后崩溃,这取决于放置了多少次 FrameLower
以及它在 canvas.
上有多少图像
我有足够的空闲 RAM,如您所料,大约 6GB,所以这不是问题。
我真正想了解的是,如果有可用内存来存储对象,为什么它会崩溃,以及为什么这些对象没有被完全删除。
我真正想做的是摆脱这个崩溃。在下面的简化示例中,我放置了 10000 帧,但在实际程序中,其中 100 帧足以让我的游戏崩溃——它们充满了图像。
(要使此代码按原样工作,需要根目录中的任何 img.gif
文件)
from tkinter import *
class FrameMain(Frame):
def __init__(self,master):
super().__init__(master,height=100,width=100,bg='black')
self.grid()
self.canvas=Canvas(self,height=100,width=100,bg='white')
self.canvas.grid()
self.__placeFrames(10000)
def __placeFrames(self,number):
for counter in range(0,number):
self.obj=self.canvas.create_window(50,50,window=FrameLower(self.canvas))
self.canvas.delete(self.obj)
del self.obj
class FrameLower(Frame):
def __init__(self,master):
super().__init__(master,height=50,width=50,bg='red')
self.canvas=Canvas(self,height=50,width=50,bg='blue')
self.canvas.grid()
self.img=PhotoImage(file='img.gif')
self.canvas.create_image(0,0,image=self.img)
def Run():
root=Tk()
frameMain=FrameMain(root)
root.mainloop()
Run()
当您执行 self.canvas.delete(self.obj)
时,您所做的只是从 canvas 中删除对象。与对象关联的框架不会被破坏。如果你想销毁 window 对象,你需要在它上面显式调用 destroy
。
canvas 在创建成千上万的项目时也有一些已知的限制。它不会回收 canvas 项目 ID,因此即使 canvas 对象本身已被删除,它们仍会继续占用少量内存。一种解决方案是不删除 canvas 项目,而是将它们移出屏幕或将它们配置为在不需要时隐藏,然后重新配置它们而不是创建新项目。
我正在为自己制作游戏。我遇到的问题是,由于某种原因,程序在将一些对象放在 canvas 上并删除它们后崩溃了。更深入:
我有框架 FrameMain
,里面有一个 canvas。
我有框架 FrameLower
,里面有一个 canvas。还有 canvas.
我正在使用 FrameMain.__placeFrames()
方法在 FrameMain
canvas 上放置和删除一些 FrameLower
作为 FrameMain.obj
。
问题是当我删除 FrameMain.obj
时,似乎某处的内存没有完全清除。所以它会导致程序在一段时间后崩溃,这取决于放置了多少次 FrameLower
以及它在 canvas.
我有足够的空闲 RAM,如您所料,大约 6GB,所以这不是问题。
我真正想了解的是,如果有可用内存来存储对象,为什么它会崩溃,以及为什么这些对象没有被完全删除。
我真正想做的是摆脱这个崩溃。在下面的简化示例中,我放置了 10000 帧,但在实际程序中,其中 100 帧足以让我的游戏崩溃——它们充满了图像。
(要使此代码按原样工作,需要根目录中的任何 img.gif
文件)
from tkinter import *
class FrameMain(Frame):
def __init__(self,master):
super().__init__(master,height=100,width=100,bg='black')
self.grid()
self.canvas=Canvas(self,height=100,width=100,bg='white')
self.canvas.grid()
self.__placeFrames(10000)
def __placeFrames(self,number):
for counter in range(0,number):
self.obj=self.canvas.create_window(50,50,window=FrameLower(self.canvas))
self.canvas.delete(self.obj)
del self.obj
class FrameLower(Frame):
def __init__(self,master):
super().__init__(master,height=50,width=50,bg='red')
self.canvas=Canvas(self,height=50,width=50,bg='blue')
self.canvas.grid()
self.img=PhotoImage(file='img.gif')
self.canvas.create_image(0,0,image=self.img)
def Run():
root=Tk()
frameMain=FrameMain(root)
root.mainloop()
Run()
当您执行 self.canvas.delete(self.obj)
时,您所做的只是从 canvas 中删除对象。与对象关联的框架不会被破坏。如果你想销毁 window 对象,你需要在它上面显式调用 destroy
。
canvas 在创建成千上万的项目时也有一些已知的限制。它不会回收 canvas 项目 ID,因此即使 canvas 对象本身已被删除,它们仍会继续占用少量内存。一种解决方案是不删除 canvas 项目,而是将它们移出屏幕或将它们配置为在不需要时隐藏,然后重新配置它们而不是创建新项目。