8000 FigureCanvasTkAgg memory leak · Issue #24820 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content
FigureCanvasTkAgg memory leak #24820
Closed
@cenfra-git

Description

@cenfra-git

Bug summary

I'm trying to update a plot in tkinter by destroying the frame where the FigureCanvasTkAgg tk widget is packed and creating another instance of FigureCanvasTkAgg, but the memory of the script only goes up after repeating the process several times.

Code for reproduction

import tkinter as tk
from tkinter import ttk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import numpy as np

class Main_Program(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        
        self.geometry("500x500")
        
        # ---------------------------------------- TOP FRAME (Button)
        
        self.top_frame = tk.Frame(self)  
        ttk.Button(self.top_frame,text="Update graph",command=self.update_graph).pack()
        self.top_frame.pack()
        
        # ---------------------------------------- BOTTOM FRAME (Graph)
        
        self.bottom_frame = tk.Frame(self) 
         
        DisplayGraph(self.bottom_frame,
        x_limit= (-10, 10) ,
        delta_x= 0.1 ,
        y_input= "2*x+2" )
        
        self.bottom_frame.pack() 
        
    
    def update_graph(self):
        
        # ----------------------------- CLEAR
        
        for widget in self.bottom_frame.winfo_children():
            widget.destroy()
        
        #  ----------------------------- DISPLAY NEW GRAPH
        
        DisplayGraph(self.bottom_frame,
        x_limit= (-10, 10) ,
        delta_x= 0.1 ,
        y_input= "2*x+2" )
        
class DisplayGraph:
    def __init__(self,passed_frame,
                x_limit=(), # TUPLE (-10,10)
                delta_x=0.0, # FLOAT 0.1
                y_input='', # STRING 2*x+2
                figsize_x=6,
                figsize_y=5):

        self.x_limit = x_limit
        self.delta_x = delta_x
        self.y_input = y_input
        
        # ---------------------------------------------------------- CREATE FIGURE AND SUBPLOT

        self.fig = Figure(figsize=(figsize_x,figsize_y),dpi=100)
        self.ax = self.fig.add_subplot(111)
        self.ax.grid()
        
        # ---------------------------------------------------------- PLOT
        
        self.plot_input()

        # ---------------------------------------------------------- PACK AND DRAW

        self.canvas_frame = tk.Frame(passed_frame,bg="black")
        self.canvas_mat = FigureCanvasTkAgg(self.fig, master=self.canvas_frame)
        
        self.canvas_mat.get_tk_widget().pack(anchor="center", expand=True,padx=2,pady=2)
        self.canvas_frame.pack(side=tk.LEFT,anchor="center", expand=True)
        
        self.canvas_mat.draw()
        
        # ----------------------------------------------------------
        
    def plot_input(self):

        x = np.arange(self.x_limit[0],self.x_limit[1],self.delta_x)
        y = eval(self.y_input)

        self.ax.plot(x,y)

App = Main_Program()
App.mainloop()

Actual outcome

Memory after running the script for the first time
image

Memory after clicking the button 20 times:
image

I've seen that some of the memory is freed after a while but not immediately after updating the frame.

Expected outcome

I would expect that destroying the frame where the FigureCanvasTkAgg widget is located would allow me to create another instance of FigureCanvasTkAgg without increasing the memory (or at least too much).

Additional information

I've seen posts as far back as 13 years ago reporting the issue in different places, but I have not been able to find a way to solve it. I know that you can create only one instance of the FigureCanvasTkAgg object and clear/plot each time, but I'm working on a project that involves several figures at the same time and closing the tkinter toplevel window does not seem to clear the memory.

Operating system

Windows

Matplotlib Version

3.6.2

Matplotlib Backend

TkAgg

Python version

3.11.0

Jupyter version

No response

Installation

pip

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0