Python QtWebagender SIGILL问题

Python QtWebagender SIGILL问题,python,pyqt,pyqt5,fedora,Python,Pyqt,Pyqt5,Fedora,我的问题总结在标题中。当我在qtwebagerenderer的实例上调用方法setHtml时,会发出SIGILL信号,并且我的应用程序会关闭 我知道这个问题是由坏的Qt5动态库引起的,但我安装它时使用了: sudo pip install PyQt5 --only-binary PyQt5 sudo pip install PyQtWebEngine --only-binary PyQtWebEngine 所以我想我会得到正确的预编译库。当我试图安装PyQt5而没有——只有二进制文件时,我总是

我的问题总结在标题中。当我在
qtwebagerenderer
的实例上调用方法
setHtml
时,会发出SIGILL信号,并且我的应用程序会关闭

我知道这个问题是由坏的Qt5动态库引起的,但我安装它时使用了:

sudo pip install PyQt5 --only-binary PyQt5
sudo pip install PyQtWebEngine --only-binary PyQtWebEngine
所以我想我会得到正确的预编译库。当我试图安装PyQt5而没有
——只有二进制文件时,我总是以一些奇怪的编译错误结束。类似于
qmake
的东西不在路径中,即使它在路径中,我可以从shell调用
qmake

所以我的问题是,如何让PyQt5在Fedora 31上运行而不使用任何符号

编辑:

以下代码可以复制该问题。关于SIGILL的信息有点不准确,因为第一个信号实际上是SIGTRAP,在我点击gdb中的
continue
之后,我得到了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()

您必须有几个限制:

  • 当在主线程中创建“web_视图”时,QObject不是这样,那么在次线程中修改它是不安全的

  • 由于QWebEnginePage任务是异步运行的,因此需要一个Qt eventloop

因此,如果要使用python的Thread类,则必须实现两个条件:

导入信号
导入系统
导入线程
从PyQt5导入QtWidgets
从PyQt5导入QtCore
从PyQt5.QtWebEngineWidgets导入QWebEnginePage
类WebView(QWebEnginePage):
定义初始化(自):
QWebEnginePage.\uuuuu初始化\uuuuuuuuu(自)
self.loadFinished.connect(self.on\u load\u finish)
def打印结果(自身、数据):
打印(“-”*30)
打印(数据)
打开(“临时html”、“wb”)作为hndl:
hndl.write(数据编码(“utf-8”))
def加载时完成(自):
toHtml(self.print\u结果)
类运行程序(threading.Thread):
定义初始化(自):
threading.Thread.\uuuuu init\uuuuuu(自)
self.daemon=True
def运行(自):
#QWebEnginePage是在新线程中创建的,并且
#该线程有一个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=qtwidts.QApplication(sys.argv)
runner=runner()
runner.start()
app.exec()
如果名称=“\uuuuu main\uuuuuuuu”:
main()

实际上
QThread
threading.Thread()
是操作系统的本机线程处理程序,因此实际上可以说QThread是一个
threading.Thread()
+
QObject
,在次线程上运行一个事件循环


另一方面,如果您的目标是从函数不属于的线程调用函数,那么应该使用异步方法,如中所述

在这种情况下,最简单的方法是使用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()
导入信号
导入系统
导入线程
从PyQt5导入QtWidgets
从PyQt5导入QtCore
从PyQt5.QtWebEngineWidgets导入QWebEnginePage
类WebView(QWebEnginePage):
定义初始化(自):
QWebEnginePage.\uuuuu初始化\uuuuuuuuu(自)
self.loadFinished.connect(self.on\u load\u finish)
def打印结果(自身、数据):
打印(“-”*30)
打印(数据)
打开(“临时html”、“wb”)作为hndl:
hndl.write(数据编码(“utf-8”))
def加载时完成(自):
toHtml(self.print\u结果)
@QtCore.pyqtlot(QtCore.QUrl)
def加载(自我,url):
QWebEnginePage.load(self,url)
类运行程序(threading.Thread):
定义初始化(自、网络视图):
self.web\u view=web\u view
threading.Thread.\uuuuu init\uuuuuu(自)
self.daemon=True
def运行(自):
url=QtCore.QUrl(“https://www.worldometers.info/coronavirus/")
QtCore.QMetaObject.invokeMethod(
self.web_视图,
“加载”,
QtCore.Qt.QueuedConnection,
QtCore.Q_ARG(QtCore.QUrl,url),
)
def main():
signal.signal(signal.SIGINT,signal.SIG_-DFL)
app=qtwidts.QApplication(sys.argv)
web_view=WebView()
runner=runner(网络视图)
runner.start()
app.exec()
如果名称=“\uuuuu main\uuuuuuuu”:
main()
或functools.partial()+QTimer

从functools导入部分
输入信号
导入系统
导入线程
从PyQt5导入QtWidgets
从PyQt5导入QtCore
从PyQt5.QtWebEngineWidgets导入QWebEnginePage
类WebView(QWebEnginePage):
定义初始化(自):
QWebEnginePage.\uuuuu初始化\uuuuuuuuu(自)
self.loadFinished.connect(self.on\u load\u finish)
def打印结果(自身、数据):
打印(“-”*30)
打印(数据)
打开(“临时html”、“wb”)作为hndl:
hndl.write(数据编码(“utf-8”))
def加载时完成(自):
toHtml(self.print\u结果)
类运行程序(threading.Thread):
定义初始化(自、网络视图):
self.web\u view=web\u view
threading.Thread.\uuuuu init\uuuuuu(自)
self.daemon=True
def运行(自):
包装器=部分(
self.web\u view.load,
QtCore.QUrl(“https://www.worldometers.info/coronavirus/"),
)
QtCore.QTimer.singleShot(0,包装器)
def main():
signal.signal(signal.SIGINT,signal.SIG_-DFL)
app=qtwidts.QApplication(sys.argv)
web_view=WebView()
runner=runner(网络视图)
runner.start()
app.exec()
如果名称=“\uuuuu main\uuuuuuuu”:

main()
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()