On Sat, 27 Feb 2021 01:06:06 +0000 MRAB <pyt...@mrabarnett.plus.com> wrote:
> 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. I just did the exact same thing, also saw no memory rise, but the window still froze after a couple of hours. Did your window freeze? Maybe the memory rise and the freeze are unrelated after all. Also, I was mistaken about Christian's second version of the Tcl code above - there is no memory rise but the window also freezes after a while. Suggests the problem is in Tcl/Tk. Thanks -- John -- https://mail.python.org/mailman/listinfo/python-list