您现在的位置是:网站首页 > 博客日记 >

pyside2在发起网络请求时如何才能不阻塞主进程

作者:YXN-python 阅读量:33 发布日期:2024-11-07

1、使用QThread进行多线程处理

创建一个继承自QThread的类,在这个类中重写run方法来执行网络请求。然后创建该类的实例,并使用start方法来触发线程,从而在后台执行网络请求,然后使用信号和槽机制将结果从工作线程传递回主线程,从而更新UI。这样可以避免网络请求阻塞主线程的UI渲染。

import sys
import requests
from PySide2.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget
from PySide2.QtCore import QThread, Signal

class Worker(QThread):
    # 定义信号
    finished = Signal(str)

    def run(self):
        # 网络请求
        response = requests.get('https://api.github.com')
        self.finished.emit(response.text)

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('PySide2非阻塞网络请求')
        self.setGeometry(100, 100, 300, 200)

        layout = QVBoxLayout()
        self.button = QPushButton('发送请求', self)
        self.button.clicked.connect(self.sendRequest)
        layout.addWidget(self.button)

        central_widget = QWidget()
        central_widget.setLayout(layout)
        self.setCentralWidget(central_widget)

    def sendRequest(self):
        self.worker = Worker()
        self.worker.finished.connect(self.onRequestFinished)
        self.worker.start()

    def onRequestFinished(self, response):
        print(response)  # 处理响应

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

有些任务我们也可以使用线程池的方式去处理

import os
from concurrent.futures import ThreadPoolExecutor


def thread_pool(func, lst, *args, **kwargs):
    with ThreadPoolExecutor(max_workers=os.cpu_count() * 2) as executor:
        return executor.map(lambda arg: func(arg, *args, **kwargs), lst)

2、使用QNetworkAccessManager进行异步网络请求

QNetworkAccessManager允许应用程序发送网络请求并接收回复,并且具有异步API,这意味着它的方法总是立即返回,而不是等到完成时才返回。而是在请求完成时发出信号,我们可以通过附加到完成信号的方法来处理响应。

import sys
from PySide2 import QtWidgets, QtCore, QtNetwork


class NetworkRequestDemo(QtWidgets.QWidget):
    def __init__(self):
        super(NetworkRequestDemo, self).__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('PySide2网络请求')
        self.setGeometry(300, 300, 300, 200)

        layout = QtWidgets.QVBoxLayout()

        self.button = QtWidgets.QPushButton('发送请求', self)
        self.button.clicked.connect(self.send_request)
        layout.addWidget(self.button)

        self.textEdit = QtWidgets.QTextEdit(self)
        self.textEdit.setReadOnly(True)
        layout.addWidget(self.textEdit)

        self.setLayout(layout)

        # 创建一个 QNetworkAccessManager 实例,用于管理网络请求
        self.nam = QtNetwork.QNetworkAccessManager()

        # 当请求完成(成功或失败)时,会调用 handleResponse 方法来处理结果
        self.nam.finished.connect(self.handle_response)

    def send_request(self):
        # 创建QUrl和QNetworkRequest对象
        url = QtCore.QUrl("http://www.example.com")
        req = QtNetwork.QNetworkRequest(url)

        # 发送GET请求
        self.nam.get(req)

    def handle_response(self, reply):
        if reply.error() == QtNetwork.QNetworkReply.NoError:
            # 请求成功,将响应数据设置为文本编辑框的内容,先将字节数据解码为字符串
            text = reply.readAll().data().decode('utf-8')
            print(text)
            self.textEdit.setText(text)
        else:
            self.textEdit.setText("Error: " + reply.errorString())

        # 删除reply对象,避免内存泄漏
        reply.deleteLater()


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    ex = NetworkRequestDemo()
    ex.show()
    sys.exit(app.exec_())

YXN-python

2024-11-07