Home > Mobile >  Avoiding garbage collection for Tkinter PhotoImage (Python)
Avoiding garbage collection for Tkinter PhotoImage (Python)

Time:12-20

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.

CodePudding user response:

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()
  • Related