我有一个在 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 工作:
You can call this function occasionally when your program is busy performing a long operation (e.g. copying a file).
删除 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()
我没有检查它,但我认为它应该有效。
好主意是启用 debug mode同时进行测试以确保一切正常。
关于python - 在同一事件循环中运行 Qt 和 Websockets 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56584743/