在同一事件循环中运行Qt和Websockets服务器



我有一个用python运行的websockets服务器,并且还想使用PyQt5显示一些GUI。websockets 和 PyQt5 都必须在同一个线程中永远运行,但我不确定我该怎么做。

下面是我实现的用于创建和启动服务器的代码。

import websockets
import asyncio

async def server_extentions(websocket, path):
    try:
        while (True):
            request = await websocket.recv()
            response = "blabla"
            await websocket.send(response)
    except websockets.ConnectionClosed as exp:
        print("connection closed.")
evt_loop = asyncio.get_event_loop()
start_server = websockets.serve(server_extentions, '127.0.0.1', 5588, loop=evt_loop)
try:
    evt_loop.run_until_complete(start_server)
    evt_loop.run_forever()
finally:
    evt_loop.run_until_complete(evt_loop.shutdown_asyncgens())
    evt_loop.close()

以下是我在应用程序中显示的一些 GUI


from PyQt5.QtWidgets import QProgressBar, QWidget, QLabel, QApplication
from PyQt5 import QtCore

class DownloadProgress(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.init_ui()
    def init_ui(self):
        self.progress_bar = QProgressBar(self)
        self.progress_bar.setGeometry(30, 40, 200, 25)
        self.progress_bar.setValue(0)
        self.label_status_msg = QLabel()
        self.label_status_msg.setAlignment(QtCore.Qt.AlignCenter)
        self.label_status_msg.setGeometry(30, 80, 200, 25)
        self.label_status_msg.setText("starting")
        self.setGeometry(300, 300, 280, 170)
        self.setWindowTitle('Bla Bla')
    def set_progress_value(self, value: int):
        self.progress_bar.setValue(value)
    def set_status_msg(self, msg: str):
        self.label_status_msg.setText(msg)
app = QApplication([])

dp = DownloadProgress()
dp.set_status_msg("download in progress.")
dp.set_progress_value(20)
dp.show()
app.exec()

给我一些光,在同一事件循环中运行这两个任务。

注意:我绝对希望它们在同一个线程中。

提前谢谢。

app.exec()运行QT的事件循环,你不能这样做,因为你必须用run_forever()运行asyncio的事件循环。

幸运的是,Qt提供了processEvents,你可以定期调用它以及asyncio的事件循环,以使Qt工作:

您可以在程序繁忙时偶尔调用此函数 执行长时间操作(例如复制文件(。


删除app.exec()并按以下方式更改代码:

app = QApplication([])
async def qt_loop():    
    while True:
        app.processEvents()     # allow Qt loop to work a bit
        await asyncio.sleep(0)  # allow asyncio loop to work a bit
qt_loop_task = asyncio.ensure_future(qt_loop())  # task will work alongside with the server

evt_loop = asyncio.get_event_loop()    
start_server = websockets.serve(server_extentions, '127.0.0.1', 5588, loop=evt_loop)
try:
    evt_loop.run_until_complete(start_server)
    evt_loop.run_forever()
finally:
    # I'll leave to you job to kill qt_loop_task 
    # see: https://stackoverflow.com/a/37345564/1113207
    evt_loop.run_until_complete(evt_loop.shutdown_asyncgens())
    evt_loop.close()

我没有检查它,但我认为它应该有效。

好主意是在测试时启用调试模式以确保一切正常。

最新更新