如果我在程序运行时监视 Windows 任务管理器,我会看到内存使用量持续上升。我编写了随附的代码来演示该问题。一旦将 tag_bind 添加到画布上,无论我如何尝试解除画布对象的绑定,内存使用量都不会下降,并且连续的绑定会要求越来越多的内存使用量。 我已经运行绑定语句数千次以放大效果。
我的代码:
from tkinter import *
import os, psutil
process = psutil.Process(os.getpid())
def showmem(): print(f'{process.memory_info().rss:,}')
root = Tk()
canvas = Canvas(root)
def bind_one(canvas, r) :
canvas.tag_unbind(r, "<ButtonPress-1>") #This has no effect on memory
def procedure(r, event) : print(r,event)
canvas.tag_bind(r, "<ButtonPress-1>", lambda event : procedure(r,event))
def unbind_all(R, canvas) :
for r in R : canvas.tag_unbind(r, "<ButtonPress-1>")
showmem()
Button(root, text = 'unbind', command = lambda : unbind_all(R, canvas)).grid()
def rebind_all(R, canvas) :
def procedure(r, event) : print(r,event)
for r in R : canvas.tag_bind(r, "<ButtonPress-1>", lambda event, r = r : procedure(r, event))
showmem()
Button(root, text = 'rebind', command = lambda : rebind_all(R, canvas)).grid()
R = []
s = 50
for j in range(6) :
for k in range(6) :
R += [canvas.create_rectangle(k*s,j*s,(k+1)*s,(j+1)*s, fill = 'white')]
x1, y1, x2, y2 = canvas.bbox('all')
canvas.config(width=x2, height=y2)
showmem()
count = 0
for k in range(2000) :
for r in R : bind_one(canvas, r) #line A
if count == 100 :
showmem()
count = 0
count += 1
showmem()
canvas.grid()
mainloop()
内存泄漏是由于 tkinter 画布更新速度太快造成的。遗憾的是,尽管您可以采取一些措施来缩小泄漏,但没有直接解决此问题的方法。
可能的修复:
您可以使用不同的 GUI 模块,例如 PyQT5,内存泄漏较少,或者您可以通过删除一些事件检查来减轻更新的负担。
这就是我能提供的一切。如果不使用武断的方法,就无法解决效率低下的问题。 :) 我希望这有帮助!