FigureCanvasTkAgg 的声明导致内存泄漏

Declaration of FigureCanvasTkAgg causes memory leak

我很难弄清楚为什么 FigureCanvasTkAgg 的声明会导致内存泄漏,我的 class __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 仍然在我的进程中 window 并且会阻塞我的计算机。然而,注释掉这三行将允许我的应用程序退出并且进程将正确终止。这些行对我的应用程序做了什么,阻止了应用程序完成后进程结束?谢谢

编辑


内存泄漏似乎仅由行 self.__fig = plt.figure(figsize=(16, 11)) 引起。我需要在退出前用 plt 做一些解构吗?

我猜这是由于 Tkinter window 关闭时 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()

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

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

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

就这样,泄漏消失了!