Python 如何清理tk.createcommand?
由于Python 如何清理tk.createcommand?,python,tkinter,tcl,Python,Tkinter,Tcl,由于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__ == "__m
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
一切正常,delf
和gc.collect()
没有效果,tk.deletecommand
将抛出\u tkinter.TclError:无法删除Tcl命令
有没有办法删除已创建的命令或清理内存?我不是使用tkinter GUI,我需要它来调用一些遗留的tcl代码
python
Python 3.7.3 (default, Mar 26 2019, 21:43:19)
[GCC 8.2.1 20181127] on linux
虽然在完整的Tcl环境中,解释器是完全可销毁的(如果不是便宜的话)对象,但Tkinter自己的引用Tcl解释器(一个相当重的实体)似乎不容易删除;它与底层C
\u tkinter
对象的生命周期相关联,这有点复杂……以至于我很难判断删除它和垃圾收集是否会导致事情变得可重新加载,或者你只是在为未来的怪异做准备。如果您没有加载Tk(因为Tk有点繁琐),它可能会工作。最终
因此,如果您不需要重新加载,最好避免重新加载,如果您不需要,最好不要创建Tcl()
的新实例。毕竟,这有点像是说创建一个新的Python解释器……所以它不应该在普通代码中的严格循环中完成
您已经找到了deletecommand
;命令的创建和销毁成本很低
是否可以在子流程中运行代码?如果没有Tk about,这应该相当简单,操作系统会非常好地清理流程。有很多方法可以做到这一点;哪一个是最好的取决于您正在做的事情的细节(特别是有多少交互性和移动多少数据)。我找到了一个解决方案,尽管这个解决方案在我的情况下不起作用。不知道为什么,但我们正在做的不仅仅是这个小演示代码,所以我切换到了
多处理
您必须显式调用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()
当心!将调用放入\uu del\uu
将无法工作,因为由于内存泄漏,析构函数永远不会被调用:
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):
f.tk.tk.deletecommand("someCommand")
print("DESTRUCTOR called!")
if __name__ == "__main__":
while 1:
f = Foo()
# f.tk.tk.deletecommand("someCommand")
del f
gc.collect()
泄漏内存的不是命令,而是您正在创建的整个Tcl环境以及
Foo
的每个实例。我不知道有什么方法可以处理这个问题。但是如果我删除createcommand
没有内存泄漏(或者至少它泄漏得很慢)。那么这是一个bug吗?最肯定的是,应该可以处理Tcl环境,或者至少是Tcl解释器。这被设计成一个可随意使用的上下文(尽管Tk有点繁琐)。但似乎没有公开。@OcasoProtal:您是否需要为每一个新的Foo()
)创建一个新的tkinter.Tcl()
实例?@stovfl很遗憾,是的,因为旧代码中存在副作用