如何清理tk.createcommand?

2024-10-01 11:35:36 发布

您现在位置:Python中文网/ 问答频道 /正文

以下示例将由于tk.createcommand创建内存泄漏:

import tkinter
import gc

class Foo:

    def __init__(self):
        self.tk = tkinter.Tcl()
        self.tk.createcommand("someCommand", self.someCommand)

    def someCommand(self):
        pass

if __name__ == "__main__":

    while 1:
        f = Foo()
        # f.tk.deletecommand("someCommand")
        # del f
        # gc.collect()

如果删除tk.createcommand一切正常,del f和{}没有效果,tk.deletecommand将抛出一个_tkinter.TclError: can't delete Tcl command。在

有没有方法可以删除创建的命令或清理内存?我不是使用tkinter GUI,我需要它来调用一些遗留的tcl代码。在

^{pr2}$

Tags: 内存importself示例footkinterdeftcl
2条回答

在完整的Tcl环境中,解释器是完全可销毁的(如果不便宜的话),Tkinter自己的引用Tcl解释器(一个相当重的实体)似乎不容易删除;它与底层C_tkinter对象的生命周期相耦合,这有点复杂…以至于我很难判断删除它和垃圾收集是否会导致重新加载,或者你是否只是在为将来的怪异做准备。如果你装东西的话,可能会有点麻烦。最终。在

因此,如果您不需要的话,可以避免重新加载,这是真正的最好的方法,如果您实际上不需要,Tcl()的新实例也最好。这毕竟有点像说“创建一个新的Python解释器……所以它不应该在普通代码中进行紧循环。在

您已经发现deletecommand;命令的创建和销毁都非常便宜。在


是否可以在子进程中运行代码?如果没有Tk about,这应该相当简单,并且操作系统可以非常好地清理进程。有很多方法可以做到这一点;哪一种方法最好取决于您正在做什么的细节(尤其是交互的程度和移动的数据量)。在

我找到了一个解决方案,尽管这个方案在我的案例中行不通。不知道为什么,但是我们做的不仅仅是这个小的演示代码,所以我切换到multiprocessing。在

必须显式调用deletecommand

import tkinter
import gc

class Foo:

    def __init__(self):
        self.tk = tkinter.Tcl()
        self.tk.createcommand("someCommand", self.someCommand)
        print("Foo intialized")
        # self.tk.eval('rename someCommand ""')

    def someCommand(self):
        pass

    def __del__(self):
        print("DESTRUCTOR called!")

if __name__ == "__main__":

    while 1:
        f = Foo()
        f.tk.tk.deletecommand("someCommand")
        del f
        gc.collect()

当心!将调用放入__del__将不起作用,因为由于内存泄漏,析构函数永远不会被调用:

^{pr2}$

相关问题 更多 >