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