【问题标题】:Tkinter Canvas Update Memory LeakTkinter Canvas 更新内存泄漏
【发布时间】:2013-10-13 07:07:26
【问题描述】:

我在下面的代码中看到了内存泄漏。我在单独的模块中创建和处理我的数据,但这不会导致我所看到的泄漏。我相信这是因为每次更改比例时我都会调用绘图类的新实例,尽管我不确定如何解决此问题。我读过this thread,但是当我尝试在我的代码上实现self.canvas.destroy() 方法时,我收到一个错误。我想知道下面的代码可以应用什么方法来解决我的问题?

代码片段:

from Tkinter import *

class Interface_On:

    def Interface_Elements(self, master):
        self.master=master
        self.master.title( "My Canvas")
        self.c=Canvas(self.master, width=1000, height=1000, bg='black')
        self.c.grid(row=0, column=0)
        menubar = Menu(master)
        filemenu = Menu(menubar, tearoff=0)
        filemenu.add_command(label="New", command=self.Edit_New)
        menubar.add_cascade(label="File", menu=filemenu)
        master.config(menu=menubar)
        drawing_utility_run=Drawing_Utility()
        drawing_utility_run.drawer(self.c)

    def Edit_New(self): 
        Export_Poscar = self.Export_Poscar = Toplevel(self.master)
        self.Export_Poscar.title('New Ribbon...')
        self.Export_Poscar.geometry('300x400')
        self.scale_Label= Label(Export_Poscar, width=15, text='scale:')
        self.scale_Label.grid(row=2, column=0)
        self.scale_Label= Label(Export_Poscar, width=15, text='scale:')
        scale_var = StringVar()
        self.scale_Spin= Spinbox(Export_Poscar, from_=1, to=1000, increment=1, width=15, command=self.execute_request_immediate, textvariable=scale_var)
        self.scale_Spin.grid(row=2, column=2)

    def execute_request_immediate(self):
        global scale
        User_Set_Scale=float(self.scale_Spin.get())
        scale=User_Set_Scale
        drawing_utility_run=Drawing_Utility()
        drawing_utility_run.drawer(self.c)

class Drawing_Utility:
    def drawer(self, canvas):
        self.canvas=canvas
        self.canvas.delete('all')
        import Generator #generates my data (imports 'scale' from above where possible)
        Generator_run=Generator.Generator()
        Generator_run.generator_go()        
        from Generator import coordinates_x_comp, coordinates_y_comp #imports necessary lists
        import Processor #Imports coordinates_x_comp, coordinates_y_comp, cleans and analyses
        Process_xy_Data=Processor.Data_Processor()
        Process_xy_Data.Process_Data()
        from Processor import p_1, p_2
        for Line in xrange(len(p_1)):
            self.canvas.create_line(p_1[Line],p_2[Line], fill='red', activefill='blue', width=1)

root=Tk()
run_it_canvas=Interface_On()
run_it_canvas.Interface_Elements(root)
root.mainloop()

【问题讨论】:

  • 使用self.canvas.destroy()时遇到什么错误?
  • TclError: 无效的命令名“.4315986616”
  • @Brionius,canvas 类中的嵌套键绑定会导致内存问题吗?

标签: python canvas memory-leaks tkinter


【解决方案1】:

我不确定这些方法是否能解决您所说的正在观察的内存泄漏问题,但我会解决一些可能会有所帮助的问题:

1。您正在使用局部变量 (drawing_utility_run) 来存储您的 Drawing_Utility 实例。目前尚不完全清楚为什么这些实例在退出时创建它们的方法后没有被垃圾收集,但无论哪种方式,似乎您可能希望该对象持久存在,因此您应该将引用存储在实例命名空间中,就像这样:

self.drawing_utility_run=Drawing_Utility()
self.drawing_utility_run.drawer(self.c)

2。当您使用 self.canvas.delete('all') 删除所有画布对象时,您依赖于您的 Tkinter 版本将字符串 'all' 实现为可识别的常量这一事实,这可能是这种情况,但不能保证。 Canvas.delete 函数将接受任何参数,无论它是否表示可识别的常量或标签/ID,而不会引发错误 - 例如尝试 self.canvas.delete('blah blah blah')。 IE。您指望self.canvas.delete('all') 删除所有对象,但对我而言,这样做并不明显。使用Tkinter 常量ALL 而不是字符串'all'

3。除非您有充分的理由让导入的模块仅存在于 Drawing_Utility 实例命名空间中,否则您应该将所有 import 语句移到模块级命名空间的顶部。

4。您的导入语句是多余的:

import Generator #generates my data (imports 'scale' from above where possible)
from Generator import coordinates_x_comp, coordinates_y_comp #imports necessary lists
import Processor #Imports coordinates_x_comp, coordinates_y_comp, cleans and analyses
from Processor import p_1, p_2

您不需要同时使用import Generatorfrom Generator import coordinates_x_comp。只需import Generator,然后参考Generator.coordinates_x_comp。通过使用这两个 import 语句,您将双重导入 Generator.coordinates_x_compProcessor.p_1 等。

【讨论】:

  • 您写道“...您依赖于您的 Tkinter 版本将字符串 'all' 实现为可识别的常量这一事实,这可能是这种情况,但不能保证。”不正确。 Tk 已经支持"all” 几十年了,并且非常重视向后兼容性非常。在可预见的将来,常量字符串"all" 绝对不会停止工作。
  • 仅仅因为它可以工作,并且可能会继续工作,并不能使它成为一个好的编程习惯。
  • 在这种特殊情况下,我不同意。 Tkinter 维护者更有可能决定在未来版本的 Tkinter 中删除或重命名 ALL 常量,而不是 "all" 将起作用。
  • 有趣 - 如果是这样的话,为什么Tkinter 作者首先要打扰ALL?为什么不将"all" 字符串硬编码到模块中?我知道Tk 是这样工作的,但我不明白为什么Tkinter 的维护者会做出这样的决定。
  • 我不知道他们在为 Tk 中的常量文字字符串创建常量时在想什么——这对我来说似乎毫无意义。我只能猜测他们试图隐藏底层实现,但我想不出这样做的正当理由。
猜你喜欢
  • 2017-11-16
  • 2013-04-02
  • 1970-01-01
  • 1970-01-01
  • 2021-07-12
  • 1970-01-01
  • 2018-04-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多