我有一个运行在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()
告诉我一些提示,以在同一事件循环中运行两个任务。
注意:我绝对希望它们在同一线程中。
谢谢。
答案 0 :(得分:1)
app.exec()
运行QT的事件循环,因为您必须使用run_forever()
运行asyncio的事件循环,所以您无法执行此操作。
幸运的是,Qt提供了processEvents,您可以在asyncio的事件循环中定期调用debug mode,以使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()
我没有检查它,但我想它应该可以工作。
好主意是在测试过程中启用Fiddle,以确保一切正常。