You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

重启包含Matplotlib画布的PyQt QApplication时崩溃如何解决?

问题根因
  • 调用QApplication.exit()只会终止Qt事件循环,不会自动销毁已经创建的主窗口、Matplotlib画布等对象,资源会残留在内存中
  • Matplotlib的Qt5Agg后端会全局持有画布的引用,第二次初始化QApplication实例时,旧的残留资源和新实例会发生冲突,直接触发崩溃
  • 仅调用self.sc.close_event()无法完全释放Matplotlib关联资源,也没有处理主窗口的销毁逻辑,残留问题没有解决
修复方案

调整退出逻辑和主循环的资源回收逻辑即可解决,修改后的完整代码如下:

import sys
import gc
import matplotlib

matplotlib.use('Qt5Agg')

from PyQt5 import QtCore, QtGui, QtWidgets


from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg, NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure


class MplCanvas(FigureCanvasQTAgg):

    def __init__(self, parent=None, width=5, height=4, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = fig.add_subplot(111)
        super(MplCanvas, self).__init__(fig)


class MainWindow(QtWidgets.QMainWindow):
    REBOOT_CODE = -654321
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self.sc = MplCanvas(self, width=5, height=4, dpi=100)
        self.sc.axes.plot([0, 1, 2, 3, 4], [10, 1, 20, 3, 40])

        button = QtWidgets.QPushButton('reload', self)
        button.clicked.connect(lambda: self.reloadapp())

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(button)
        layout.addWidget(self.sc)

        widget = QtWidgets.QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)


    def reloadapp(self):
        self.sc.close_event()
        # 主动销毁主窗口,释放所有Qt控件资源
        self.close()
        # 释放Matplotlib画布关联的figure资源,清除后端全局引用
        del self.sc.figure
        QtWidgets.QApplication.exit(MainWindow.REBOOT_CODE)


if __name__ == '__main__':
    exit_code = MainWindow.REBOOT_CODE
    while exit_code == MainWindow.REBOOT_CODE:
        app = QtWidgets.QApplication(sys.argv)
        w = MainWindow()
        w.show()
        exit_code = app.exec_()
        # 手动删除窗口和应用实例
        del w
        del app
        # 强制垃圾回收,清理所有残留的未释放资源
        gc.collect()

核心改动点:

  1. 退出前先调用self.close()销毁主窗口,释放所有Qt控件占用的资源
  2. 删除Matplotlib画布关联的figure对象,清除后端全局持有的引用
  3. 事件循环结束后手动删除窗口和应用实例,配合垃圾回收保证所有残留资源被清理

内容的提问来源于stack exchange,提问作者Maracman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 10:15:01