为啥 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.2
和PyQt5.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 请求拦截器等改进。
【讨论】:
正如你所说,我忽略了我的interceptor
和profile
在构造函数退出后正在死去。我会考虑升级到 5.13,但似乎库结构不同,所以我暂时推迟它。我发布了一个您可能能够回答的不同问题:***.com/questions/56923879/…。谢谢!以上是关于为啥 QWebEngineUrlRequestInterceptor 在 app.quit() 之后仍然存在的主要内容,如果未能解决你的问题,请参考以下文章
为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?