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

Why is QWebEngineUrlRequestInterceptor still alive after app.quit()

我有一个带有 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 被调用并且我的应用程序存在,拦截器的线程应该停止。

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

void QWebEnginePage::loadFinished(bool ok)

This signal is emitted when the page finishes loading content. This signal is independent of script execution or page rendering. ok will indicate whether the load was successful or any error occurred.

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

在这种情况下,QWebEngineUrlRequestInterceptor 可以解决未决请求,因为该部分不是由 Qt 处理,而是由 Chromium 处理。

我在您的代码中看到的一个问题是 QWebEngineProfile 在 QWebEnginePage 被破坏之前被破坏导致问题。这种情况下的解决方案是使 class.

的配置文件和拦截器成员
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 and PyQtWebEngine 5.13.0,因为它带来了改进,例如 thread-safe 和页面特定的 url 请求拦截器。