我有一个 pyqt 应用程序,它必须通过 websockets 与客户端通信。我设法在 qt 环境之外的 python 脚本中创建服务器,但是当我包含 asyncio.run 时,它冻结了 qt 应用程序。因此我尝试创建一个继承的 QThread 类来处理 websocket 函数:
class WSThread(QThread):
def __init__(self, port, loop, parent=None):
super(WSThread, self).__init__(parent)
self.clients = []
self.port = port
self.loop = loop
def run(self):
server = websockets.serve(self.handler, "", self.port)
self.loop.run_until_complete(server)
self.loop.run_forever()
# async def start_server(self):
# await self.server.wait_closed()
async def send(self, websocket, message):
try:
await websocket.send(message)
except websockets.ConnectionClosed:
pass
async def broadcast(self, message):
if self.clients: # asyncio.wait doesn't accept an empty list
await asyncio.wait([
asyncio.create_task(self.send(websocket, message))
for websocket in self.clients
])
async def handler(self, websocket, path):
self.clients.append(websocket)
async for message in websocket:
await self.broadcast(message)
目标是将服务器上收到的消息传输给所有连接的客户端。我的代码肯定不是最优的,但它与 Qt 分开工作。
我在这样的 QDialog 类中使用它:
class MyDialog(QDialog)
def __init__(self, parent=None):
super(MyDialog, self).__init__(parent)
tb = QPushButton()
tb.setText("Start WS")
tb.clicked.connect(self.start_ws)
self.layout = QVBoxLayout()
self.layout.addWidget(tb)
self.setLayout(self.layout)
def start_ws(self):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop = asyncio.get_event_loop()
ws = WSThread(WS_PORT, loop)
ws.start()
dlg = MyDialog()
dlg.show()
但是我收到一条错误消息:
RuntimeError: There is no current event loop in thread 'Dummy-3'.
。我不理解这条消息,因为我正在创建循环并将其作为参数传递给线程类。