我有一个用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()
我没有检查它,但我认为它应该有效。
好主意是在测试时启用调试模式以确保一切正常。