gpt4 book ai didi

python - Qt (PyQt) 事件循环内的 xmlrpc?

转载 作者:行者123 更新时间:2023-12-01 08:08:58 24 4
gpt4 key购买 nike

我想将 xmlprc 服务器与 Qt 应用程序一起使用,在这种情况下是 Qt Web 引擎,以便 xmlrpc 客户端可以向其发送命令。我必须与现有客户合作。

这里有两个事件循环。运行 Qt 的 exec_() 是阻塞的,运行 xmlrpc 的 serve_forever() 是阻塞的。

我首先想知道您是否知道 Python 的 xmlrpc 库可以与 Qt 的事件循环很好地集成。所以一切都可以开箱即用。

<小时/>

我没有找到,所以我尝试在线程内启动 rpc 服务器。它基本上可以工作,但无法与 Qt 小部件交互。我们怎样才能做到这一点?

下面是 pyqt5==5.12 和 PyQtWebEngine。

from PyQt5.QtCore import QUrl from PyQt5.QtCore import QThread
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtWidgets import QVBoxLayout
from PyQt5.QtWidgets import QWidget

from xmlrpc.server import SimpleXMLRPCServer

# Qt
URL_START = "http://ddg.gg"

app = QApplication([])
window = QWidget()
layout = QVBoxLayout()

webview = QWebEngineView()
webview.setUrl(QUrl(URL_START))

minibuffer = QWebEngineView()
mb_prompt = """
<html>
<div> hello minibuffer </div>
</html>
"""
minibuffer.setHtml(mb_prompt)

layout.addWidget(webview)
layout.addWidget(minibuffer)

window.setWindowTitle("My browser")
window.setLayout(layout)
window.show()

# xmlrpc
def hello(name):
return "hello " + name

def set_minibuffer(name):
return minibuffer.setHtml(mb_prompt.replace("minibuffer", name))


class RPCThread(QThread):
def run(self):
# sleep a little bit to make sure QApplication is running.
self.sleep(1)
print("--- starting server…")
self.rpcserver = SimpleXMLRPCServer(("localhost", 8282))
self.rpcserver.register_function(hello)
self.rpcserver.register_function(set_minibuffer)

self.rpcserver.serve_forever()

class RPCWidget(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.thread = RPCThread(self)
self.thread.start()

rpcwidget = RPCWidget()
rpcwidget.show()

# Qt main loop.
print("--- Qt loop")
app.exec_()

来自客户端:

from xmlrpc.client import ServerProxy
client = ServerProxy("http://localhost:8282"
print(client.hello("me")) # OK
# Trying to set the web engine's html content:
print(client.set_minibuffer("me") # fails

失败了

--- starting server…
127.0.0.1 - - [27/Mar/2019 16:52:01] "POST /RPC2 HTTP/1.1" 200 -
Received signal 11 SEGV_MAPERR 000000000000
#0 0x7f9b5bf3e8bf <unknown>
#1 0x7f9b5bf3ecbb <unknown>
#2 0x7f9b5bf3f33e <unknown>
#3 0x7f9b6667ef20 <unknown>
#4 0x7f9b5b9f3515 <unknown>
#5 0x7f9b5b9f37eb <unknown>
#6 0x7f9b5b9f3b79 <unknown>
#7 0x7f9b5a4731c0 QtWebEngineCore::WebContentsAdapter::setContent()
#8 0x7f9b610c7bf5 QWebEnginePage::setHtml()
#9 0x7f9b612fb824 meth_QWebEngineView_setHtml
#10 0x0000005030d5 <unknown>
#11 0x000000506859 _PyEval_EvalFrameDefault
#12 0x000000504c28 <unknown>
#13 0x00000058644b <unknown>
#14 0x00000059ebbe PyObject_Call
#15 0x000000507c17 _PyEval_EvalFrameDefault
[…]

最佳答案

您有 2 个错误:

  • 您不能也不得直接从另一个线程修改 GUI,在您的情况下,set_minibuffer() 是在 SimpleXMLRPCServer 所在的线程中执行的。相反,您必须通过 pyqtSignalQMetaObject::invokeMethod、自定义 QEventsQTimer.singleShot(0, ... )

  • 我不是 xmlrpc 专家,但 Why can't xmlrpc client append item to list accessable via xmlrpc server procedure? ,它表示您必须将 SimpleXMLRPCServer 对象传递给构造函数 allow_none = True

考虑到上述情况,解决方案是:

from functools import partial

# ...

from PyQt5.QtCore import QTimer

# ...

def set_minibuffer(name):
html = mb_prompt.replace("minibuffer", name)
wrapper = partial(minibuffer.setHtml, html)
QTimer.singleShot(0, wrapper)
return html


class RPCThread(QThread):
def run(self):
# sleep a little bit to make sure QApplication is running.
self.sleep(1)
print("--- starting server…")
self.rpcserver = SimpleXMLRPCServer(("localhost", 8282), allow_none=True)
self.rpcserver.register_function(hello)
self.rpcserver.register_function(set_minibuffer)

self.rpcserver.serve_forever()

# ...

关于python - Qt (PyQt) 事件循环内的 xmlrpc?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55382314/

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