为啥 QWebEngineUrlRequestInterceptor 在 app.quit() 之后仍然存在

Posted

技术标签:

【中文标题】为啥 QWebEngineUrlRequestInterceptor 在 app.quit() 之后仍然存在【英文标题】:Why is QWebEngineUrlRequestInterceptor still alive after app.quit()为什么 QWebEngineUrlRequestInterceptor 在 app.quit() 之后仍然存在 【发布时间】:2019-07-07 06:06:24 【问题描述】:

我有一个带有 QWebEngineUrlRequestInterceptor 的 PyQt5 QWebEnginePage。运行app.exec_()后,Interceptor按预期工作,但是页面加载完成后,即回调 在执行self.loadFinished.connect(self._on_load_finished),并运行self.app.quit(),再次调用QWebEngineUrlRequestInterceptor.interceptRequest()函数,导致错误Received signal 11 <unknown> 000000000000 和脚本崩溃。

class WebEngineUrlRequestInterceptor(QWebEngineUrlRequestInterceptor):
    def __init__(self, on_network_call):
        super().__init__()
        self.on_network_call = on_network_call

    def interceptRequest(self, info):
        self.on_network_call(info)


class PyQtWebClient(QWebEnginePage):
  def __init__(self, url):
    self.app = QApplication(sys.argv)

    interceptor = WebEngineUrlRequestInterceptor(self.on_network_call)
    profile = QWebEngineProfile()
    profile.setRequestInterceptor(interceptor)

    super().__init__(profile, None)

    self.loadFinished.connect(self._on_load_finished)
    self.html = ""

    self.network_requests = 

    self.load(QUrl(url))
    self.app.exec_()

  def on_network_call(self, info):
    # Something ...


  def _on_load_finished(self):
    self.toHtml(self.callable)

  def callable(self, html_str):
    self.html = html_str
    self.app.quit()

试过PyQt5.11.2PyQt5.10.1 我期待以下两件事之一: - 如果页面上仍有待处理的请求,则不应调用 self.loadFinished。 - 如果 self.loadFinished 被调用并且我的应用程序存在,拦截器的线程应该停止。

【问题讨论】:

【参考方案1】:

loadFinished 表示页面内容已完成加载,如文档所示:

void QWebEnginePage::loadFinished(bool ok)

当页面完成加载内容时会发出此信号。这 信号独立于脚本执行或页面渲染。好的,会的 指示加载是否成功或发生任何错误。

但这并不意味着页面一直在发出请求,例如您可以通过 AJAX 发出请求,所以不要混淆这些概念。

在这种情况下,QWebEngineUrlRequestInterceptor 可能正在解决待处理的请求,因为该部分不是由 Qt 而是由 chromium 处理的。

我在您的代码中看到的一个问题是 QWebEngineProfile 在 QWebEnginePage 被破坏之前被破坏,从而导致问题。这种情况下的解决方案是让profile和interceptor成为类的成员。

class PyQtWebClient(QWebEnginePage):
    def __init__(self, url):
        self.app = QApplication(sys.argv)

        self.interceptor = WebEngineUrlRequestInterceptor(self.on_network_call)
        self.profile = QWebEngineProfile()
        self.profile.setRequestInterceptor(self.interceptor)

        super().__init__(self.profile, None)
        # ...

最后我推荐使用最新版本的PyQt5 5.13.0 和PyQtWebEngine 5.13.0,因为它带来了线程安全和页面特定的url 请求拦截器等改进。

【讨论】:

正如你所说,我忽略了我的interceptorprofile 在构造函数退出后正在死去。我会考虑升级到 5.13,但似乎库结构不同,所以我暂时推迟它。我发布了一个您可能能够回答的不同问题:***.com/questions/56923879/…。谢谢!

以上是关于为啥 QWebEngineUrlRequestInterceptor 在 app.quit() 之后仍然存在的主要内容,如果未能解决你的问题,请参考以下文章

为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?

为啥需要softmax函数?为啥不简单归一化?

为啥 g++ 需要 libstdc++.a?为啥不是默认值?

为啥或为啥不在 C++ 中使用 memset? [关闭]

为啥临时变量需要更改数组元素以及为啥需要在最后取消设置?

为啥 CAP 定理中的 RDBMS 分区不能容忍,为啥它可用?