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