【问题标题】:Declaration of FigureCanvasTkAgg causes memory leakFigureCanvasTkAgg 的声明导致内存泄漏
【发布时间】:2015-08-22 22:43:39
【问题描述】:

我很难弄清楚为什么声明 FigureCanvasTkAgg 会导致内存泄漏,我的课程 __init__ 方法中有以下几行:

   # pndwinBottom is a paned window of the main screen
   self.__drawplotFrame = Frame(pndwinBottom, width=WIDTH, height=HEIGHT)                                 # the frame on which we will add our canvas for drawing etc.

   self.__fig = plt.figure(figsize=(16,11))
   self.__drawplotCanvas = FigureCanvasTkAgg(self.__fig, master=self.__drawplotFrame)

问题是,在运行我的应用程序并退出时,python32.exe 仍保留在我的进程窗口中,并且会阻塞我的计算机。但是,注释掉这三行将允许我的应用程序退出并且该过程将正确终止。这些行对我的应用程序有什么影响,以防止在应用程序完成后进程结束?谢谢

编辑


内存泄漏似乎仅由 self.__fig = plt.figure(figsize=(16, 11)) 行引起。在退出之前我是否需要对 plt 进行某种解构?

【问题讨论】:

    标签: python python-2.7 matplotlib memory-leaks tkinter


    【解决方案1】:

    我遇到了内存泄漏问题,我想我找到了解决方案。在我的 __init__ 方法中,我创建了一个框架,然后将其传递给绘图函数来完成实际工作。在该函数中,我将创建一个新的 matplotlib.figure.Figure 实例,由于某种原因,该实例在函数超出范围时没有被破坏。

    为了解决这个问题,我这样做了:在 __init__ 方法中,我不仅创建了框架,还创建了图形(带有轴)和画布:

        results = tk.Frame(self)
        f = Figure()
        ax0 = f.add_subplot(211)
        ax1 = f.add_subplot(212)
        self.canvas = FigureCanvasTkAgg(f, results)
        self.canvas.get_tk_widget().pack(expand=True, fill='both')
    

    那么,在绘图方法内部,

        ax0, ax1 = self.canvas.figure.get_axes()
        ax0.clear()
        ax0.plot(x, y)
    
        ax1.clear()
        ax1.plot(x, z)
    
        self.canvas.draw()
    

    就这样,泄漏消失了!

    【讨论】:

    • 这解决了我在 python3.8 中使用 FigureCanvasTkAgg 遇到的一个非常相似的问题;显然,一次调用 FigureCanvasTkAgg 并根据需要制作和清除子图是要走的路!
    【解决方案2】:

    我猜这是由于关闭 Tkinter 窗口时 pyplot 图形没有被破坏造成的。
    就像在embedding in tk example 中尝试使用Figure

    from matplotlib.figure import Figure
    
    self.__fig = Figure(figsize=(16,11))
    

    示例使用:

    import Tkinter as tk
    import matplotlib
    matplotlib.use('TkAgg')
    
    from matplotlib.figure import Figure
    from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
    
    class App():
        def __init__(self, parent):
    
            self.__drawplotFrame = tk.Frame(parent, width=500, height=500)
            self.__drawplotFrame.pack()
    
            self.__fig = Figure(figsize=(16,11))
            self.__p = self.__fig.add_subplot(1,1,1)
            self.__p.plot(range(10), range(10))
    
            self.__drawplotCanvas = FigureCanvasTkAgg(self.__fig, master=self.__drawplotFrame)
            self.__drawplotCanvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
    
    root = tk.Tk()
    App(root)
    root.mainloop()
    

    【讨论】:

    • 谢谢,似乎做到了,pyplot.figurematplotlib.figure 之间有什么区别,为什么 pyplot 给我内存泄漏? EDIT 实际上,一切似乎都有效,直到我最终绘制了一些东西到这个数字上,然后它似乎再次停止了进程清理
    • 我真的不知道比this answer 中的区别更多。关于您的编辑,我也在我的示例中绘制了一些东西,您是否以相同的方式绘制?还是我的例子也给你带来了问题?
    • 我认为您的答案是正确的,因为您确实解决了我的问题,但是我还有另一个错误导致额外的内存泄漏。调用 plot 函数时,现在看来 im = plt.imshow(regrid_atten_back, cmap = cm, aspect = 'auto', norm = plot_norm, extent = extents, interpolation = None) 行会导致程序无法正确释放 matplotlib。 plt 在这种情况下是 pyplot。此行用于在实际绘图的右侧显示一个颜色条
    • 再一次,不要使用 pyplot。 self.__p.imshow(...) 应该与我的示例中定义的 self.__p 一起使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-16
    • 2015-07-14
    • 2015-07-06
    • 2014-06-07
    • 2013-11-20
    • 2011-10-28
    相关资源
    最近更新 更多