PyQt5 使用 aiohttp 发送异步请求

PyQt5 使用 aiohttp 发送异步请求

本文使用PyQt5演示,如何结合aiohttp库,发送异步请求

代码结构

本文中全部代码全在test_async_request.py这一个文件中编码,步骤中有变动的地方会注释标注,无改动的不会重复显示出来,需要看完整代码的,可直接移步到末尾。

需要安装PyQt5,aiohttp==3.8.6,asyncqt

一. 创建测试页面

首先我们需要创建一个窗口,用于显示请求响应的内容

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ File        : test_async_request.py
@ Author      : yqbao
@ Version     : V1.0.0
@ Description : 使用 aiohttp 发送异步请求
"""
import sys
import asyncio
from PyQt5.QtWidgets import QApplication, QPushButton, QLabel, QVBoxLayout, QWidget
import aiohttp
from asyncqt import QEventLoop


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.setFixedSize(800, 80)
        self.setWindowTitle("PyQt5 使用 aiohttp")

        # 创建 QLabel QPushButton
        self.label = QLabel("按下按钮发出请求", self)
        self.button = QPushButton("发送 GET 请求", self)

        # 设置布局
        layout = QVBoxLayout()
        layout.addWidget(self.label)
        layout.addWidget(self.button)
        self.setLayout(layout)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

运行后,可以得到下面这样的窗口
image

二. 实现异步请求

使用aiohttp实现异步请求

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ File        : test_async_request.py
@ Author      : yqbao
@ Version     : V1.0.0
@ Description : 使用 aiohttp 发送异步请求
"""
class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        ...  # 忽略

        self.button.clicked.connect(self.handle_request)

    def handle_request(self):
        # 在事件循环中运行异步函数
        asyncio.create_task(self.fetch_data())

    async def fetch_data(self):
        url = 'https://api.github.com/repos/YQBaobao/RollerCoaster/tags'
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as response:
                if response.status == 200:
                    data = await response.json()
                    tags = [tag['name'] for tag in data][:3]
                    # 更新标签
                    self.label.setText(f"Title: {tags}")
                else:
                    self.label.setText(f"请求失败: {response.status}")

但是此时我们不能直接运行,因为:PyQt5 的事件循环与 asyncio 的事件循环不兼容,需要手动运行 asyncio 的事件循环。

三. 手动启动事件循环

为了解决事件循环不兼容问题,可以使用 asyncioQEventLoop 或者 asyncqt 库来桥接 asyncioPyQt5 的事件循环。
以下是使用 asyncqt 库举例

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ File        : test_async_request.py
@ Author      : yqbao
@ Version     : V1.0.0
@ Description : 使用 aiohttp 发送异步请求
"""
class MainWindow(QWidget):
        ...  # 忽略无变化


if __name__ == "__main__":
    app = QApplication(sys.argv)

    # 创建 asyncio 事件循环
    loop = QEventLoop(app)
    asyncio.set_event_loop(loop)

    window = MainWindow()
    window.show()
    # sys.exit(app.exec_())
    # 在 asyncio 事件循环中运行应用程序
    with loop:
        sys.exit(loop.run_forever())

启动,并点击发送 GET 请求 按钮:
image

四. 完整代码

完整代码见:GitHubGitee

本文章的原文地址
GitHub主页

posted @ 2024-10-14 14:33  星尘的博客  阅读(23)  评论(0编辑  收藏  举报