[…] Tk will not keep a reference to [image objects]. When the last Python reference to the image object is deleted, the image data is deleted as well, and Tk will display an empty box wherever the image was used.
—tkinter — Python interface to Tcl/Tk — Python 3.14.4 documentation
I am wondering what prevents Python from fixing this.
The Tk image command has the inuse option, which can be used to determine if an image is in use in any widget. Is it unsuitable for this purpose?
Or is it necessary to keep this behavior to maintain backwards compatibility? That would make sense, but Python doesn’t guarantee when garbage collection happens. That means that programs already can’t expect that removing all references to an image will lead to immediate graphical effects.
So, is there a reason why this behavior can’t be fixed/made more intuitive?
No, the names of images that are only in use in widgets would be stored in a list/queue. The elements of this list would be periodically checked whether they are still in use by widgets.
One possibility of implementing this periodic check is to make Image.__init__() pick one image name from this list, and check it. (However, the check would also need to happen elsewhere, to avoid leaking memory if all images are loaded before they can become unused.)
The question is more like: what algorithm should be used to prioritize the checks of specific images? For example, I imagine it would be useful to check larger images more often than smaller ones, and I would also check long-used images less often than newly created images.
This would be a complex and slow implementation of garbage collector. Every check will need to scan all images in that list, so it gets slower as the list size grows. And you need to run the check often, after each operation which can potentially make the image unused, and perhaps additionally run it periodically, several times per second, because some internal Tk code can make the image unused.
It is much easier to keep the reference to the Image object while you need it, for example as an attribute of the widget that uses it. If the widget object is destroyed, the reference to the Image object will be removed, and if it was the last reference, it itself will be destroyed.