Tkinter wart: bug or feature?

Mike Clarkson support at internetdiscovery.com
Fri Nov 15 16:17:02 EST 2002


This started out as a bug report by Peter Deutsch about disappearing
bitmap images:

https://sourceforge.net/tracker/?func=detail&atid=105470&aid=632323&group_id=5470

which I seconded because of a bug I had found in
Demo/tix/tixwidgets.py where the author had written in a procedure:

    image1 = Tkinter.Image('photo', file=file)
    lbl = Tkinter.Label(win.window, image=image1)
    lbl.pack(expand=1, fill=Tix.BOTH)

The image will not show up if the variable image1 is not
declared global. I couldn't figure out why the global was
necessary and put a comment in the code over a year ago.
What seemed to me to be the equivalent code worked:

    image1 = win.tk.eval('image create photo -file %s'  % file)
    lbl = Tkinter.Label(win.window, image=image1)
    lbl.pack(expand=1, fill=Tix.BOTH)

Martin Loewis explained that:

>When the BitmapImage object is no longer referenced, it is
>finalized; finalization causes "image delete" to be invoked.

>Tcl does not keep a reference to the image object; if you
>don't yourself, nobody does. In turn, the image object goes
>away right after being created.

And sure enough, the Tkinter.Image class has a __del__ method
that does an image delete on the image, so when the procedure
finishes it deletes the image image1 even though Label wants to make
use of it. Guido decided to close this as Not A Bug, even though the
originator of the bug report strongly disgreed, so I wanted to put it
out to c..l.p to get feedback.

It looks like a Bug to me for 3 reasons.

1) My understanding of Python was that when warts are really ugly
they get classed as a bug. This is really ugly because when I do

    text1 = "My Label"
    lbl = Tkinter.Label(win.window, text=text1)

I don't have to make text1 global for it to work. As Peter said:
 No other commonly used entity in the Tkinter API has this
 counter-intuitive behavior. Widgets do not disappear from
 the screen if Python holds no references to them. Text
 strings do not disappear from the screen if Python holds no
 references to the string object or the font object. 

2) Tkinter is a wrapper to Tk  and Tk does not delete unreferenced
images, so nor should Tkinter. Unreferenced images are not garbage
in Tk because they can always be referenced again using image_names().
Images have to be explicitly deleted and so should it be in Tkinter.

3) As Peter pointed out:
 Python does not, and cannot, guarantee that an object
 will be finalized and freed immediately when there are no
 longer any references to it: if the object must be reclaimed
 by garbage collection, an unpredictable amount of time may
 elapse. Therefore, in my opinion, it is very undesirable to
 use object finalization in a way that directly affects the
 user interface.

Martin claims that "anybody looking at the Image class code
could not fail to notice the image delete"  but this is obviously not
true, as the bug had been sitting for years in the tixwidgets.py code
until I tracked it down, and that was written by people who presumably
knew Tkinter well, as they have written Tix.py, the largest Tkinter
wrapper I know of outside of Tkinter itself. 

Comments? Is this a bug or a feature?

Mike





More information about the Python-list mailing list