On 2021-02-26 23:59, John O'Hagan wrote:
On Fri, 26 Feb 2021 08:19:14 +0100
Christian Gollwitzer <aurio...@gmx.de> wrote:

Am 26.02.21 um 06:15 schrieb John O'Hagan:
[...]
> > I've followed your suggestions as per my last post, and can confirm
> the same freezing behaviour when running your code directly as a
> tclsh script on Debian Testing, Tcl 8.6.11. You might report this as a bug to the Tcl bugtracker https://core.tcl-lang.org/tk/ticket

I guess the problem is with the steady creation of widgets. Tk was
not meant to be used like that. Tkinter creates new widget names for
each widget with random numbers, just like the Tcl code above does,
whereas in a usual Tcl/Tk program the names are given by the
programmer.

Thanks, I will make the bug report. However, based  on your comments
above, it looks similar to this one, closed as invalid 16 years ago:

https://core.tcl-lang.org/tk/tktview/1173484fffffffffffff

This was also related to memory "creep" caused by Tk's cache of names,
which AIUI is a Tk design feature (but I don't know Tk!).

Can you also check this program, which reuses the same widget path
name, albeit does the creation/destruction in cycles:

======================
package require Tk

proc randint {} {
     expr {int(rand()*10000000)}
}

proc display {label} {
     destroy $label
     set label [label .l -text [randint]]
     pack $label
     after 100 [list display $label]
}

display [label .l]
========================


I have tried this overnight and it is still running, not frozen and with
no apparent increase in memory use. I guess that is likely the issue. I
don't know Tcl/Tk - is there a way to emulate the above approach of
re-using the widget name in tkinter?

As mentioned by others, typically you wouldn't continuously recreate
new widgets, but either update the text of the widget
(label['text']="New text") or attaching a StringVar() )

or, if you must rearrange the widgets, you pack_forget() them and
then repack them.

        Christian

This is possible of course, but will require more than a repack. In my
use case, each widget is an attribute of a Python object, intended
control and display data about that object, and there is an
indeterminate number of such objects at any given time. I had
assumed I could just destroy the widget and let the object go out of
scope to be garbage collected. I'll need to redesign this altogether if
I can't rely on Tk to manage memory.

IMHO it's quite surprising if .destroy doesn't free all the resources
used by a widget!

I've look in Lib\tkinter\__init__.py and it appears that you can give it a name, so:

from tkinter import *
from random import randint

root = Tk()

def display(label):
     label.destroy()
     label = Label(name='my_label', text=randint(0, 9))
     label.pack()
     root.after(1, display, label)

display(Label(name='my_label'))
mainloop()

When I do that I'm not seeing a memory rise.
--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to