【问题标题】: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 被调用并且我的应用程序存在,拦截器的线程应该停止。

【问题讨论】:

    标签: python pyqt pyqt5 qtwebengine


    【解决方案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.0PyQtWebEngine 5.13.0,因为它带来了线程安全和页面特定的url 请求拦截器等改进。

    【讨论】:

    • 正如你所说,我忽略了我的interceptorprofile 在构造函数退出后正在死去。我会考虑升级到 5.13,但似乎库结构不同,所以我暂时推迟它。我发布了一个您可能能够回答的不同问题:stackoverflow.com/questions/56923879/…。谢谢!
    猜你喜欢
    • 2015-09-30
    • 1970-01-01
    • 2011-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-02
    • 1970-01-01
    • 2018-09-26
    相关资源
    最近更新 更多