tkinter, matplotlib: memory usage tkinter, matplotlib: memory usage tkinter tkinter

tkinter, matplotlib: memory usage


Try calling gc.collect() after the toplevel window has been closed:

def new_child(self):    tl = TL()    self.wait_window(tl)   # Wait for tl to be closed before continuing execution    del tl    gc.collect()


Thank you for this question, and for the answer which helped me a lot. I have found myself in a similar situation with a slightly more complex GUI. I experienced memory leaks despite applying the solution given here. It seems that adding traces to Tkinter variables (e.g. IntVar, DoubleVar, etc) prevents the Toplevel window from being properly destroyed, and causes leaks. Manually removing the traces on destroy fixes this issue. Let me give an example of a code which suffers a leak, and the fix I found. I hope it helps others.

Preliminary:First of all, use the corrected version of new_child given by Josselin:

def new_child(self):    tl = TL()    self.wait_window(tl)   # Wait for tl to be closed before continuing execution    del tl    gc.collect()

Then, the code with a memory leak (caused by the trace):

class TL(Toplevel):    def __init__(self, **kw):        Toplevel.__init__(self, **kw)        self.number = IntVar()        self.data = "00000000000"*10000000  # just some data to analyze memory allocation         self._figure = MyFigure(self.data)        self._canvas = FigureCanvasTkAgg(self._figure, master=self)        self._canvas.get_tk_widget().grid(row=0, column=0, sticky="NSWE")        Spinbox(self, from_=0, to=10, textvariable=self.number).grid(row=1,column=0)        self.number.trace('w', self.updateSomething)    def updateSomething(self, *args): return

And finally, the fix (remove manually the traces on destroy):

class TL(Toplevel):    def destroy(self):        for var, s, trid in self.allTraces: var.trace_vdelete(s, trid) #manually removes traces. Otherwise: memory leak!        super(TL, self).destroy()    def __init__(self, **kw):        Toplevel.__init__(self, **kw)        self.allTraces = []        self.number = IntVar()        self.data = "00000000000"*10000000  # just some data to analyze memory allocation         self._figure = MyFigure(self.data)        self._canvas = FigureCanvasTkAgg(self._figure, master=self)        self._canvas.get_tk_widget().grid(row=0, column=0, sticky="NSWE")        Spinbox(self, from_=0, to=10, textvariable=self.number).grid(row=1,column=0)        trid = self.number.trace('w', self.updateSomething)        self.allTraces.append((self.number, 'w', trid))    def updateSomething(self, *args): return