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