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

QWebEngineView创建多QWebEngineProcess致内存过高求助

QWebEngineView销毁后QWebEngineProcess未终止的问题

我的应用里有一组按钮,点击每个按钮会在QMainWindow中创建新的QWebEngineView。关闭QMainWindow时,我希望销毁QWebEngineView及其衍生的QWebEngineProcess,但实际没做到——多次点击按钮会生成多个占用内存的QWebEngineProcess。为什么销毁Web视图后这些进程还没终止?

进程截图

以下是用于排查问题的示例代码,点击按钮会创建带QWebEngineView的新主窗口:

import sys
from PySide6.QtWidgets import (QApplication, QWidget, QVBoxLayout, QPushButton, QMainWindow)
from PySide6 import QtCore
from PySide6.QtWebEngineWidgets import QWebEngineView


class PlotWindow(QMainWindow):
    def __init__(self, parent):
        """Constructor."""
        super(PlotWindow, self).__init__(parent)
        self.webV = QWebEngineView()
        self.webV.load('https://en.wikipedia.org/')
        self.setCentralWidget(self.webV)


    def closeEvent(self, event):
        self.webV.destroy() # => 这不会终止后台的QWebEngineProcess进程



class webView(QWidget):
    def __init__(self):
        super(webView, self).__init__()

        self.layout = QVBoxLayout(self)
        btn = QPushButton('Click')
        btn.clicked.connect(lambda: self.create_plot(self))
        self.layout.addWidget(btn)

        self.setLayout(self.layout)

    @QtCore.Slot()
    def create_plot(self, widget):
        win = PlotWindow(widget)
        win.show()


if __name__ == "__main__":
    app = QApplication()

    web = webView()
    web.show()

    sys.exit(app.exec())

我了解到Qt文档中的“Process Per Site”模式可能是解决方案,但不知道怎么正确使用命令行参数,直接传入QApplication()无效。


问题原因

  1. Qt WebEngine的进程管理是独立于Qt控件生命周期的,默认进程模型会复用或保留进程资源,不会随视图销毁立刻终止进程
  2. destroy()仅销毁Qt控件对象,不会主动触发WebEngine进程的终止逻辑

解决方案

方案1:正确释放WebEngine资源并清理页面

修改PlotWindow的closeEvent方法,先清理页面资源再释放控件:

def closeEvent(self, event):
    # 加载空白页面,清理当前页面的资源占用
    self.webV.load(QtCore.QUrl("about:blank"))
    # 等待页面加载完成,确保资源清理完毕
    loop = QtCore.QEventLoop()
    self.webV.loadFinished.connect(loop.quit)
    loop.exec()
    # 解除父控件关联并延迟销毁
    self.webV.setParent(None)
    self.webV.deleteLater()
    # 确认关闭窗口
    event.accept()

方案2:配置"Process Per Site"进程模型

需要在QApplication初始化之前添加命令行参数,而不是直接传入初始化方法:

if __name__ == "__main__":
    # 添加进程模型配置参数
    sys.argv.append("--process-model=process-per-site")
    app = QApplication(sys.argv)

    web = webView()
    web.show()

    sys.exit(app.exec())

该模式会将同一站点的页面归到同一个进程中,减少进程数量,当该站点的所有视图都关闭后,对应的进程会自动终止。

方案3:使用独立Profile控制进程生命周期

为每个视图创建独立的QWebEngineProfile,关闭视图时销毁Profile,触发进程终止:

from PySide6.QtWebEngineWidgets import QWebEnginePage, QWebEngineProfile

class PlotWindow(QMainWindow):
    def __init__(self, parent):
        super(PlotWindow, self).__init__(parent)
        # 创建独立的Profile
        self.profile = QWebEngineProfile()
        self.webV = QWebEngineView()
        # 为视图绑定独立Profile的页面
        self.webV.setPage(QWebEnginePage(self.profile, self.webV))
        self.webV.load('https://en.wikipedia.org/')
        self.setCentralWidget(self.webV)

    def closeEvent(self, event):
        self.webV.load(QtCore.QUrl("about:blank"))
        loop = QtCore.QEventLoop()
        self.webV.loadFinished.connect(loop.quit)
        loop.exec()
        self.webV.deleteLater()
        # 销毁Profile,触发对应进程终止
        self.profile.deleteLater()
        event.accept()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 18:52:42