I'm using MacOS v 12.6 and Python v 3.9.6. Why does the code below garbage collect the image unless the commented-out line is uncommented? Isn't using self.img
supposed to be enough to avoid garbage collection?
from tkinter import Tk, Label
from PIL import Image, ImageTk
import numpy as np
class Meter:
def __init__(self, root):
self.root = root
self.pos, self.img = (None,) * 2
k = np.empty((300,300,3), dtype=np.uint8)
k[:,:] = (10,) * 3
img = Image.fromarray(k, "RGB")
self.img = ImageTk.PhotoImage(img)
self.label = Label(self.root, image=self.img)
# self.label.foo = self.img
self.label.pack()
if __name__ == "__main__":
root = Tk()
Meter(root)
root.mainloop()
I've used ImageTk
several times and for some reason am having problems avoiding garbage collection this time. I found this answer, which directed me to add the commented-out line, and it solved my problem. But like the answerer, I don't know why. The comments for this answer didn't clarify the issue, and the answer is quite old, so I am asking here.
Isn't using self.img supposed to be enough to avoid garbage collection?
It is, except that self
refers to an instance of Meter
and you're not keeping a reference to the instance of Meter
. So, the garbage collector thinks you're done with the instance of Meter
and tries to free up memory.
If you save an instance, then self.img
inside Meter
will be enough:
if __name__ == "__main__":
root = Tk()
meter = Meter(root)
#^^^^^^^
root.mainloop()