如何在 PyQt 中实现异步数据库请求

需求

开发软件的时候不可避免要和数据库发生交互,但是有些 SQL 请求非常耗时,如果在主线程中发送请求,可能会造成界面卡顿。这篇博客将会介绍一种让数据库请求变得和前端的 ajax 请求一样简单,且不会阻塞界面的异步请求方法。

实现过程

在实现异步请求之前,需要先明确一下函数签名:

def sqlRequest(service: str, method: str, slot, params: dict = None
)

各个参数的解释如下:

  • service: 业务名
  • method: 接口名
  • slot: 拿到数据后调用的回调函数
  • params: 请求参数

总体流程如下图所示,包括子界面发送请求、数据库线程处理请求、主界面调用回调函数来消费响应结果三个步骤。

image

信号总线

在 Qt 中,子线程无法直接更新主界面,只能发送信号通知主线程,然后在主线程中更新界面。在之前的博客《如何在 pyqt 中实现全局事件总线》介绍了信号总线的使用,通过引入信号总线,可实现任意层级的组件之间的通信。

本文的信号总线只含有两个信号,一个用来请求数据,一个用来消费数据:

class SignalBus(QObject):""" Signal bus """fetchDataSig = Signal(SqlRequest)    # 请求数据信号dataFetched = Signal(SqlResponse)    # 响应数据信号signalBus = SignalBus()class SqlRequest:""" Sql request """def __init__(self, service: str, method: str, slot=None, params: dict = None):self.service = serviceself.method = methodself.slot = slotself.params = params or {}class SqlResponse:""" Sql response """def __init__(self, data, slot):self.slot = slotself.data = data

发送请求

子界面中通过调用 sqlRequest() 函数来发起异步 SQL 请求,该函数只是将参数封装为 SqlRequest 对象,然后通过 signalBusfetchDataSig 信号发送给数据库子线程:

def sqlRequest(service: str, method: str, slot=None, params: dict = None):""" query sql from database """request = SqlRequest(service, method, slot, params)signalBus.fetchDataSig.emit(request)

比如下图中商品类型下拉框的数据就来自于数据库:

image

在组件 LicenseCard 中使用下述代码就能完成数据的请求和消费(组件库参见 https://qfluentwidgets.com/zh/ ):

from qfluentwidgets import HeaderCardWidget, ComboBoxclass LicenseCard(HeaderCardWidget):def __init__(self, parent=None):super().__init__("许可证", parent)self.goodsComboBox = ComboBox(self)# 请求商品信息sqlRequest("goodsService", "listAll", lambda i: self.onGoodsFetched(i))def onGoodsFetched(self, goods: List[Goods]):""" 将商品信息添加到下拉框中 """for good in goods:self.goodsComboBox.addItem(good.name, userData=good)

处理请求

子线程 DatabaseThread 中维护着一个请求队列 tasks,每当收到信号总线的 fetchDataSig 信号时,就会使用反射机制将请求中携带的 servicemethod 字符串转换为数据库业务类的方法指针,并将这个指针添加到队列中等待调用。调用方法返回的数据会被封装为 SqlResponse 对象,接着通过信号总线发送给主界面。

class DatabaseThread(QThread):""" Database thread """def __init__(self, db: QSqlDatabase = None, parent=None):super().__init__(parent=parent)self.database = Database(db, self)self.tasks = deque()# 处理请求信号signalBus.fetchDataSig.connect(self.onFetchData)def run(self):""" 处理请求 """while self.tasks:task, request = self.tasks.popleft()result = task(**request.params)signalBus.dataFetched.emit(SqlResponse(result, request.slot))def onFetchData(self, request: SqlRequest):""" 将请求添加到队列中 """service = getattr(self.database, request.service)task = getattr(service, request.method)self.tasks.append((task, request))if not self.isRunning():self.start()class Database(QObject):""" Database """def __init__(self, db: QSqlDatabase = None, parent=None):super().__init__(parent=parent)self.orderService = OrderService(db)self.userService = UserService(db)self.goodsService = GoodsService(db)

处理响应结果

主界面中只需将信号总线的 dataFetched 信号连接槽函数,然后在槽函数中对取出 response 对象中的数据,并调用回调函数来消费数据即可:

from qfluentwidgets import MSFluentWindowclass MainWindow(MSFluentWindow):""" 主界面 """def __init__(self):super().__init__()# 处理响应结果signalBus.dataFetched.connect(self.onDataFetched)def onDataFetched(self, response: SqlResponse):if response.slot:response.slot(response.data)

总结

在这篇博客中我们使用子线程和信号总线完成了异步数据库请求操作,界面所使用的组件全部来自于 https://qfluentwidgets.com/zh/ ,以上~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/204818.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

hive映射es表任务失败,无错误日志一直报Task Transitioned from NEW to SCHEDULED

一、背景 要利用gpt产生的存放在es种的日志表做统计分析,通过hive建es的映射表,将es的数据拉到hive里面。 在最初的时候同事写的是全量拉取,某一天突然任务报错,但是没有错误日志一直报:Task Transitioned from NEW t…

Nature Communications 高时空分辨率的机器人传感系统及其在纹理识别方面的应用

前沿速览: 现有的触觉传感器虽然可以精确的检测压力、剪切力和应变等物理刺激,但还难以像人类手指一样通过滑动触摸,同时获取静态压力与高频振动来实现精确的纹理识别。为了解决这一问题,来自南方科技大学的郭传飞团队提出了衔接…

Angular 由一个bug说起之三:为什么时不时出现额外的水平/垂直滚动条?怎样能更好的防止它的出现?

目录: 什么是单元溢出 控制滚动条出现的属性 怎样能减少意外的滚动条出现 一、什么是单元溢出 在说到这个问题之前我们先简单阐述一下视图窗口(Viewport)和视图内容(View Content) 视图窗口简单来说就是呈现内容的视口,浏览器就是一个窗口&#xff…

安装Centos7

作者:余小小 下载VMware15 参考:http://t.csdnimg.cn/saS9S 下载镜像 这里使用网易镜像库下载 网易开源镜像站http://mirrors.163.com/ 网易Centos下载http://mirrors.163.com/centos/7.7.1908/isos/x86_64/ 安装Centos系统(基础设施&…

C++初阶(十四)list

📘北尘_:个人主页 🌎个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上,不忘来时的初心 文章目录 一、 list的介绍二、list的模拟实现1、list的节点2、list 的迭代器3、list4、打印5、完整代码…

[LeetCode]-283. 移动零-1089. 复写零

目录 283. 移动零 描述 解析 代码 1089. 复写零 描述 解析 代码 283. 移动零 283. 移动零https://leetcode.cn/problems/move-zeroes/ 描述 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 请注意 &…

数据结构与算法编程题50

假设不带权有向图采用邻接矩阵G存储,设计实现以下功能的算法。 (1)求出图中每个顶点的出度。 (2)求出图中出度为0的顶点数。 (3)求出图中每个顶点的入度。 //参考博客:https://blog.…

想要精通GO语言?这些网站是你的最佳选择!

介绍:Go(又称 Golang)是由 Google 的 Robert Griesemer,Rob PGo(又称 Golang)是由 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 开发的一种静态强类型、编译型语言。它在2009年11月10…

matplotlib与opencv图像读取与显示的问题

个人博客:Sekyoro的博客小屋 个人网站:Proanimer的个人网站 最近在用opencv和matplotlib展示图片,但是遇到了一些问题,这里展开说说 首先需要明确的是,opencv和matplotlib读取图片都是通道在最后,而前者默认可见光图像是BGR,后者是RGB.此外还有PIL以及imageio等读取图像的工具…

如何使用cpolar+Plex在Windows系统上搭建私人媒体影音站点公网可访问

文章目录 1.前言2. Plex网站搭建2.1 Plex下载和安装2.2 Plex网页测试2.3 cpolar的安装和注册 3. 本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1.前言 用手机或者平板电脑看视频,已经算是生活中稀松平常的场景了,特别是各…

ERP软件定制开发对企业的优势|app小程序搭建

ERP软件定制开发对企业的优势|app小程序搭建 随着科技的不断发展,企业管理也面临了更多的挑战。为了更好地适应市场需求和提高运营效率,越来越多的企业开始选择使用ERP软件进行管理。然而,市场上现成的ERP软件并不能完全满足企业的需求&#…

兰州电力博物馆 | OLED透明展示台:创新展示,增强互动体验

产品:8片55寸OLED透明屏 应用场景:OLED透明屏利用其高透明度的特点,可以叠加在文物展示台上面,这种展示方式既让观众看到了文物原貌,又能了解其内部结构和细节特点,打破空间的束缚。 项目时间&#xff1a…

opencv知识库:cv2.add()函数和“+”号运算符

需求场景 现有一灰度图像,需求是为该图像增加亮度。 原始灰度图像 预期目标图像 解决方案 不建议的方案——“”运算符 假设我们需要为原始灰度图像的亮度整体提升88,那么利用“”运算符的源码如下: import cv2img_path r"D:\pych…

SCADA软件工具有多少免费的?

随着工业自动化的飞速发展,SCADA系统已经成为工业领域智能化转型绕不开的重要工具,不少个人和公司也都加入到了学习研究SCADA系统的队伍中。数维图小编耗费大量时间整理了国内外免费(非完全免费)的SCADA软件工具,有部分…

电源模块测试系统测试稳压电源 提升电源稳定性和可靠性

稳压电源是用来将不稳定的电压转换为稳定的输出电压的电子装置,其性能、稳定性和可靠性直接影响着工作状态。稳压电源测试是保证电子设备稳定工作的重要环节,那么如何测试稳压电源呢? 一、静态测试 静态测试是通过万用表或数字电压表测量稳压电源的输出…

ComplexHeatmap热图专栏 | 6. 3D热图绘制教程

本期教程 原文链接https://mp.weixin.qq.com/s/EyBs6jn78zOomcTv1aP52g 6 3D热图的绘制教程 基于《热图绘制教程》专栏,本教程已更新了5个章节,不知道大家是否有所收获。对于小杜个人来说,真的需要不断的复习和练习才可以记住,但…

RedHat9中安装Mysql8.0+出现“错误:GPG 检查失败“的处理

近期通过VM安装了RedHat9,之后在RedHat9中安装Mysql8.0的时候出现了个问题:“错误:GPG 检查失败”,如图所示: 解决方案:重新导入新的秘钥即可,如下所示: rpm --import https://rep…

vr建筑虚拟实景展厅漫游体验更直观全面

随着科技的不断进步,纯三维、可交互、轻量化的三维线上展览云平台,打破时间界限,以其独特的魅力,给予客户更多的自主性、趣味性和真实性,客户哪怕在天南地北,通过网络、手机即可随时随地参观企业线上立体化…

泳道图绘制全攻略,一图胜千言,快速上手

泳道图是一种流程图的形式,通过在不同的泳道中展示不同的参与者,帮助我们更好地理解和分析流程。它是一种非常有用的工具,可以帮助我们在团队协作、流程管理和问题解决等方面取得更好的效果。 1. 泳道图的定义 泳道图是一种以泳道为基础的流程…

浅析pyqt事件机制

pyqt事件机制 一、什么是pyqt事件机制? ​ 事件是指用户操作或系统发生的各种动作,比如鼠标点击、键盘输入、窗口大小变化等。事件可以由用户或操作系统触发,然后被传递给应用程序进行处理。PyQt的事件机制通过事件循环(Event L…