gpt4 book ai didi

python - QtWebPageRenderer SIGILL 问题

转载 作者:行者123 更新时间:2023-12-04 09:40:57 30 4
gpt4 key购买 nike

我的问题总结在标题中。当我调用方法 setHtmlQtWebPageRenderer 的实例上,发出 SIGILL 信号,我的应用程序出现故障。

我知道这个问题是由糟糕的 Qt5 动态库引起的,但我安装了它:

sudo pip install PyQt5 --only-binary PyQt5
sudo pip install PyQtWebEngine --only-binary PyQtWebEngine

所以我想我会得到正确的预编译库。当我尝试在没有 --only-binary 的情况下安装 PyQt5 时,我总是以一些奇怪的编译错误结束。像 qmake不在 PATH 中,但我可以调用 qmake从壳。

所以我的问题是,如何让 PyQt5 在没有任何 SIGILL 的情况下在 Fedora 31 上运行。

编辑:

以下代码可以复制该问题。关于 SIGILL 的信息有点不准确,因为第一个信号实际上是 SIGTRAP,在我点击 continue 之后在 gdb 中,我得到了 SIGILL。这暗示 Qt 实际上是想对我说些什么,虽然不是很直观。

玩了一阵子后,我发现没有线程,没关系。这是否意味着 Qt 强制用户使用 QThread 而不是 python 线程?或者这意味着我不能在运行事件循环的线程之外调用 Qt 对象的方法?
import signal
import sys
import threading
from PyQt5 import QtWidgets
from PyQt5 import QtCore
from PyQt5.QtWebEngineWidgets import QWebEnginePage


class WebView(QWebEnginePage):
def __init__(self):
QWebEnginePage.__init__(self)
self.loadFinished.connect(self.on_load_finish)

def print_result(self, data):
print("-" * 30)
print(data)
with open("temp.html", "wb") as hndl:
hndl.write(data.encode("utf-8"))

def on_load_finish(self):
self.toHtml(self.print_result)


class Runner(threading.Thread):
def __init__(self, web_view):
self.web_view = web_view
threading.Thread.__init__(self)
self.daemon = True

def run(self):
self.web_view.load(QtCore.QUrl("https://www.worldometers.info/coronavirus/"))


def main():
signal.signal(signal.SIGINT, signal.SIG_DFL)
app = QtWidgets.QApplication(sys.argv)
web_view = WebView()
runner = Runner(web_view)
runner.start()
app.exec_()


if __name__ == "__main__":
main()

最佳答案

你必须有几个限制:

  • QObject 不是 thread-safe所以在主线程中创建“web_view”时,在辅助线程中修改它是不安全的
  • 由于 QWebEnginePage 任务异步运行,因此您需要一个 Qt 事件循环。

  • 所以如果你想使用 python 的 Thread 类,那么你必须同时实现这两个条件:

    import signal
    import sys
    import threading
    from PyQt5 import QtWidgets
    from PyQt5 import QtCore
    from PyQt5.QtWebEngineWidgets import QWebEnginePage


    class WebView(QWebEnginePage):
    def __init__(self):
    QWebEnginePage.__init__(self)
    self.loadFinished.connect(self.on_load_finish)

    def print_result(self, data):
    print("-" * 30)
    print(data)
    with open("temp.html", "wb") as hndl:
    hndl.write(data.encode("utf-8"))

    def on_load_finish(self):
    self.toHtml(self.print_result)


    class Runner(threading.Thread):
    def __init__(self):
    threading.Thread.__init__(self)
    self.daemon = True

    def run(self):
    # The QWebEnginePage was created in a new thread and
    # that thread has an eventloop
    loop = QtCore.QEventLoop()
    web_view = WebView()
    web_view.load(QtCore.QUrl("https://www.worldometers.info/coronavirus/"))
    loop.exec_()


    def main():
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    app = QtWidgets.QApplication(sys.argv)
    runner = Runner()
    runner.start()
    app.exec_()


    if __name__ == "__main__":
    main()

    现实中 QThreadthreading.Thread()是 native 线程 处理程序 操作系统,所以实际上可以说 QThread 是一个 threading.Thread() + QObject在辅助线程上运行事件循环。

    另一方面,如果你的目标是从一个不属于它的线程调用一个函数,那么你应该使用 this answer 中指出的异步方法。 .

    在这种情况下,最简单的是使用 pyqtSlot + QMetaObject:
    import signal
    import sys
    import threading

    from PyQt5 import QtWidgets
    from PyQt5 import QtCore
    from PyQt5.QtWebEngineWidgets import QWebEnginePage


    class WebView(QWebEnginePage):
    def __init__(self):
    QWebEnginePage.__init__(self)
    self.loadFinished.connect(self.on_load_finish)

    def print_result(self, data):
    print("-" * 30)
    print(data)
    with open("temp.html", "wb") as hndl:
    hndl.write(data.encode("utf-8"))

    def on_load_finish(self):
    self.toHtml(self.print_result)

    @QtCore.pyqtSlot(QtCore.QUrl)
    def load(self, url):
    QWebEnginePage.load(self, url)



    class Runner(threading.Thread):
    def __init__(self, web_view):
    self.web_view = web_view
    threading.Thread.__init__(self)
    self.daemon = True

    def run(self):
    url = QtCore.QUrl("https://www.worldometers.info/coronavirus/")
    QtCore.QMetaObject.invokeMethod(
    self.web_view,
    "load",
    QtCore.Qt.QueuedConnection,
    QtCore.Q_ARG(QtCore.QUrl, url),
    )



    def main():
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    app = QtWidgets.QApplication(sys.argv)
    web_view = WebView()
    runner = Runner(web_view)
    runner.start()
    app.exec_()


    if __name__ == "__main__":
    main()

    或 functools.partial() + QTimer
    from functools import partial
    import signal
    import sys
    import threading

    from PyQt5 import QtWidgets
    from PyQt5 import QtCore
    from PyQt5.QtWebEngineWidgets import QWebEnginePage


    class WebView(QWebEnginePage):
    def __init__(self):
    QWebEnginePage.__init__(self)
    self.loadFinished.connect(self.on_load_finish)

    def print_result(self, data):
    print("-" * 30)
    print(data)
    with open("temp.html", "wb") as hndl:
    hndl.write(data.encode("utf-8"))

    def on_load_finish(self):
    self.toHtml(self.print_result)


    class Runner(threading.Thread):
    def __init__(self, web_view):
    self.web_view = web_view
    threading.Thread.__init__(self)
    self.daemon = True

    def run(self):
    wrapper = partial(
    self.web_view.load,
    QtCore.QUrl("https://www.worldometers.info/coronavirus/"),
    )
    QtCore.QTimer.singleShot(0, wrapper)



    def main():
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    app = QtWidgets.QApplication(sys.argv)
    web_view = WebView()
    runner = Runner(web_view)
    runner.start()
    app.exec_()


    if __name__ == "__main__":
    main()

    关于python - QtWebPageRenderer SIGILL 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62330952/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com