在函数或类中使用QApplication::exec()



我希望下面的代码在web加载过程中获得从http://down.51en.com:88开始的请求url,然后使用url的响应对象进行其他处理。在我的程序中,一旦targetUrl赋值,我希望函数targetUrlGetter(url)返回给调用者,然而,问题是,QApplication::exec()进入主事件循环所以不能执行代码结束的时候targetUrlGetter() exec()调用函数之后,因此,函数不能返回,我试过用qApp.quit() interceptRequest(self, info)为了告诉应用程序退出,这样targetUrlGetter(url)可以返回,但功能仍不能返回,程序甚至崩溃退出这个主题(测试32位),那么我如何将targetUrl返回给调用程序呢?

这里的困难是如何在不崩溃的情况下退出Qt事件循环,并将请求url返回给调用者。

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtWebEngineCore import *
from PyQt5.QtCore import *

class WebEngineUrlRequestInterceptor(QWebEngineUrlRequestInterceptor):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.page = parent
    def interceptRequest(self, info):
        if info.requestUrl().toString().startswith('http://down.51en.com:88'):
            self.targetUrl = info.requestUrl().toString()
            print('----------------------------------------------', self.targetUrl)
            qApp.quit()
            # self.page.load(QUrl(''))

def targetUrlGetter(url=None):
    app = QApplication(sys.argv)
    page = QWebEnginePage()
    globalSettings = page.settings().globalSettings()
    globalSettings.setAttribute(
        QWebEngineSettings.PluginsEnabled, True)
    globalSettings.setAttribute(
        QWebEngineSettings.AutoLoadImages, False)
    profile = page.profile()
    webEngineUrlRequestInterceptor = WebEngineUrlRequestInterceptor(page)
    profile.setRequestInterceptor(webEngineUrlRequestInterceptor)
    page.load(QUrl(url))
    # view = QWebEngineView()
    # view.setPage(page)
    # view.show()
    app.exec_()
    return webEngineUrlRequestInterceptor.targetUrl

url = "http://www.51en.com/news/sci/everything-there-is-20160513.html"
# url = "http://www.51en.com/news/sci/obese-dad-s-sperm-may-influence-offsprin.html"
# url = "http://www.51en.com/news/sci/mars-surface-glass-could-hold-ancient-fo.html"
targetUrl = targetUrlGetter(url)
print(targetUrl)

您应该始终在程序开始时初始化QApplication,并始终在程序结束时调用QApplication::exec函数。

另一件事是QWebEngineUrlRequestInterceptor.interceptRequest是一个异步调用的回调函数。由于info.requestUrl().toString()是在回调函数内部调用的,因此无法同步地获取return的结果。

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtWebEngineCore import *
from PyQt5.QtCore import *

class WebEngineUrlRequestInterceptor(QWebEngineUrlRequestInterceptor):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.page = parent
    def interceptRequest(self, info):
        if info.requestUrl().toString().startswith('http://down.51en.com:88'):
            self.targetUrl = info.requestUrl().toString()
            print('----------------------------------------------', self.targetUrl)
            # Don't do thatDo you really want to exit the whole program?
            # qApp.quit()
            # Do something here, rather than return it.
            # It must be run asynchronously
            # self.page.load(QUrl(''))

def targetUrlGetter(url=None):
    page = QWebEnginePage()
    globalSettings = page.settings().globalSettings()
    globalSettings.setAttribute(
        QWebEngineSettings.PluginsEnabled, True)
    globalSettings.setAttribute(
        QWebEngineSettings.AutoLoadImages, False)
    profile = page.profile()
    webEngineUrlRequestInterceptor = WebEngineUrlRequestInterceptor(page)
    profile.setRequestInterceptor(webEngineUrlRequestInterceptor)
    page.load(QUrl(url))
    # view = QWebEngineView()
    # view.setPage(page)
    # view.show()
    # Don't return this. It cannot be called synchronously. It must be called asynchronously.
    # return webEngineUrlRequestInterceptor.targetUrl
app = QApplication(sys.argv)  # always initialize QApplication at the beginning of the program
url = "http://www.51en.com/news/sci/everything-there-is-20160513.html"
# url = "http://www.51en.com/news/sci/obese-dad-s-sperm-may-influence-offsprin.html"
# url = "http://www.51en.com/news/sci/mars-surface-glass-could-hold-ancient-fo.html"
targetUrl = targetUrlGetter(url)
print(targetUrl)
app.exec_() # always call the QApplication::exec at the end of the program

最新更新