Tkinter long-running window freezes

MRAB python at mrabarnett.plus.com
Wed Feb 24 19:27:33 EST 2021


On 2021-02-24 23:23, John O'Hagan wrote:
> On Wed, 24 Feb 2021 13:07:24 +0000
> MRAB <python at mrabarnett.plus.com> wrote:
> 
>> On 2021-02-24 11:35, John O'Hagan wrote:
> [...]
>> > 
>> > Here is some minimal, non-threaded code that reproduces the problem
>> > on my system (Xfce4 on Debian testing):
>> > 
>> > from tkinter import *
>> > from random import randint
>> > 
>> > root = Tk()
>> > 
>> > def display(label):
>> >      label.destroy()
>> >      label = Label(text=randint(0, 9))
>> >      label.pack()
>> >      root.after(100, display, label)
>> > 
>> > display(Label())
>> > mainloop()
>> >   
> [...]
>> > This works for 3-4 hours, but eventually the window freezes.
>> > 
>> > The process uses about 26 Mb of memory at first, and this gradually
>> > increases to around 30 or so by the time it freezes.
>> > 
>> > Any ideas what could be causing this, or even how to approach
>> > debugging or workarounds?
>> >   
>> The problem might be that you're adding the label using .pack but not 
>> removing it with .pack_forget when you destroy it.
>> 
>> Try doing both:
>> 
>> from tkinter import *
>> from random import randint
>> 
>> root = Tk()
>> 
>> def display(label):
>>      if label is not None:
>>          label.pack_forget()
>>          label.destroy()
>> 
>>      label = Label(text=randint(0, 9))
>>      label.pack()
>>      root.after(100, display, label)
>> 
>> display(None)
>> mainloop()
> 
> Thanks for the reply, I ran this overnight but unfortunately the result
> was the same.
> 
> I'm not a tkinter expert at all, but I had gathered from the docs that
> calling destroy() on a widget was sufficient to cleanly remove the
> widget and all its children. Is that not the case?
> 
> In case it's relevant, to clarify what I mean by "freeze": the window
> continues to display the digits indefinitely if no attempt is made to
> interact with the window, but after some hours have passed, if I click
> on the window the digits stop displaying, resizing causes fragmented
> images of the desktop to appear in the window, and it cannot be closed
> except by terminating the process (e.g, in a task manager).
> 
Hmm. A memory leak perhaps? It's more noticeable if you reduce the 
timeout from 100 to 1.
A workaround is to update the label's text instead:

from tkinter import *
from random import randint

root = Tk()

def update():
      label.config(text=randint(0, 9))
      root.after(1, update)

label = Label()
label.pack()
update()
mainloop()

It's neater anyway.


More information about the Python-list mailing list