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

标签 python websocket pyqt python-asyncio

我有一个在 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/

相关文章:

networking - 如何调试Websocket?

android - 如何在 ionnic 和 android 上使用 websockets?

qt - 如何让文字填满QLabel的所有空间?

python - Python和PyQt:从另一个类运行函数

python - 使用 PyInstaller (Python 2) 后为 "ImportError: cannot import name _imaging"

python - Numpy.点阵乘法: (n-by-m)*(m-by-k) and (m-by-k)*(k-by-n) have very different speeds

javascript - 使用 Web 套接字将 Canvas 内容从客户端传递给管理员

python - PyQt5,如何使用 QAbstractButton 制作图像切换按钮

python - 查找自上次使用 python imaplib2 检查后添加到 imap 邮箱的新邮件?

python - python中如何在某些情况下终止进程