欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

PyQt實現(xiàn)異步數(shù)據(jù)庫請求的實戰(zhàn)記錄

 更新時間:2023年12月08日 08:16:26   作者:之一Yo  
開發(fā)軟件的時候不可避免要和數(shù)據(jù)庫發(fā)生交互,但是有些 SQL 請求非常耗時,如果在主線程中發(fā)送請求,可能會造成界面卡頓,本文將介紹一種讓數(shù)據(jù)庫請求變得和前端的 ajax 請求一樣簡單,希望對大家有所幫助

需求

開發(fā)軟件的時候不可避免要和數(shù)據(jù)庫發(fā)生交互,但是有些 SQL 請求非常耗時,如果在主線程中發(fā)送請求,可能會造成界面卡頓。這篇博客將會介紹一種讓數(shù)據(jù)庫請求變得和前端的 ajax 請求一樣簡單,且不會阻塞界面的異步請求方法。

實現(xiàn)過程

在實現(xiàn)異步請求之前,需要先明確一下函數(shù)簽名:

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

各個參數(shù)的解釋如下:

  • service: 業(yè)務名
  • method: 接口名
  • slot: 拿到數(shù)據(jù)后調用的回調函數(shù)
  • params: 請求參數(shù)

總體流程如下圖所示,包括子界面發(fā)送請求、數(shù)據(jù)庫線程處理請求、主界面調用回調函數(shù)來消費響應結果三個步驟。

信號總線

在 Qt 中,子線程無法直接更新主界面,只能發(fā)送信號通知主線程,然后在主線程中更新界面。在之前的博客《如何在 pyqt 中實現(xiàn)全局事件總線》介紹了信號總線的使用,通過引入信號總線,可實現(xiàn)任意層級的組件之間的通信。

本文的信號總線只含有兩個信號,一個用來請求數(shù)據(jù),一個用來消費數(shù)據(jù):

class SignalBus(QObject):
    """ Signal bus """
    fetchDataSig = Signal(SqlRequest)    # 請求數(shù)據(jù)信號
    dataFetched = Signal(SqlResponse)    # 響應數(shù)據(jù)信號

    
signalBus = SignalBus()
    
    
class SqlRequest:
    """ Sql request """

    def __init__(self, service: str, method: str, slot=None, params: dict = None):
        self.service = service
        self.method = method
        self.slot = slot
        self.params = params or {}


class SqlResponse:
    """ Sql response """

    def __init__(self, data, slot):
        self.slot = slot
        self.data = data

發(fā)送請求

子界面中通過調用 sqlRequest() 函數(shù)來發(fā)起異步 SQL 請求,該函數(shù)只是將參數(shù)封裝為 SqlRequest 對象,然后通過 signalBus 的 fetchDataSig 信號發(fā)送給數(shù)據(jù)庫子線程:

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)

比如下圖中商品類型下拉框的數(shù)據(jù)就來自于數(shù)據(jù)庫:

在組件 LicenseCard 中使用下述代碼就能完成數(shù)據(jù)的請求和消費(組件庫參見 https://qfluentwidgets.com/zh/ ):

from qfluentwidgets import HeaderCardWidget, ComboBox

class LicenseCard(HeaderCardWidget):
    
    def __init__(self, parent=None):
        super().__init__("許可證", parent)
        self.goodsComboBox = ComboBox(self)
        
        # 請求商品信息
        sqlRequest("goodsService", "listAll", self.onGoodsFetched)

    def onGoodsFetched(self, goods: List[Goods]):
        """ 將商品信息添加到下拉框中 """
        for good in goods:
            self.goodsComboBox.addItem(good.name, userData=good)

處理請求

子線程 DatabaseThread 中維護著一個請求隊列 tasks,每當收到信號總線的 fetchDataSig 信號時,就會使用反射機制將請求中攜帶的 service 和 method 字符串轉換為數(shù)據(jù)庫業(yè)務類的方法指針,并將這個指針添加到隊列中等待調用。調用方法返回的數(shù)據(jù)會被封裝為 SqlResponse 對象,接著通過信號總線發(fā)送給主界面。

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 信號連接槽函數(shù),然后在槽函數(shù)中對取出 response 對象中的數(shù)據(jù),并調用回調函數(shù)來消費數(shù)據(jù)即可:

from qfluentwidgets import MSFluentWindow

class MainWindow(MSFluentWindow):
    """ 主界面 """
    
    def __init__(self):
        super().__init__()
        
        # 處理響應結果
        signalBus.dataFetched.connect(self.onDataFetched)

    def onDataFetched(self, response: SqlResponse):
        if response.slot:
            response.slot(response.data)

到此這篇關于PyQt實現(xiàn)異步數(shù)據(jù)庫請求的實戰(zhàn)記錄的文章就介紹到這了,更多相關PyQt異步數(shù)據(jù)庫請求內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 基于Python實現(xiàn)剪切板實時監(jiān)控方法解析

    基于Python實現(xiàn)剪切板實時監(jiān)控方法解析

    這篇文章主要介紹了基于Python實現(xiàn)剪切板實時監(jiān)控方法解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-09-09
  • Python實現(xiàn)的科學計算器功能示例

    Python實現(xiàn)的科學計算器功能示例

    這篇文章主要介紹了Python實現(xiàn)的科學計算器功能,涉及Python基于數(shù)值運算與事件響應實現(xiàn)科學計算器功能相關操作技巧,需要的朋友可以參考下
    2017-08-08
  • Python利用smtplib實現(xiàn)郵件發(fā)送

    Python利用smtplib實現(xiàn)郵件發(fā)送

    在當今數(shù)字時代,電子郵件已成為我們生活和工作中不可或缺的一部分,本篇文章將為你講解如何在Python發(fā)送郵件,并為你提供實現(xiàn)的多種方式,希望對大家有所幫助
    2023-06-06
  • python線程池ThreadPoolExecutor,傳單個參數(shù)和多個參數(shù)方式

    python線程池ThreadPoolExecutor,傳單個參數(shù)和多個參數(shù)方式

    這篇文章主要介紹了python線程池ThreadPoolExecutor,傳單個參數(shù)和多個參數(shù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • python共軛梯度法特征值迭代次數(shù)討論

    python共軛梯度法特征值迭代次數(shù)討論

    這篇文章主要介紹了python共軛梯度法特征值迭代次數(shù)討論,想了解共軛梯度法的同學,需要著重看一下
    2021-04-04
  • python?pandas遍歷每行并累加進行條件過濾方式

    python?pandas遍歷每行并累加進行條件過濾方式

    這篇文章主要介紹了python?pandas遍歷每行并累加進行條件過濾方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • 跟老齊學Python之集成開發(fā)環(huán)境(IDE)

    跟老齊學Python之集成開發(fā)環(huán)境(IDE)

    IDE的全稱是:Integrated Development Environment,簡稱IDE,也稱為Integration Design Environment、Integration Debugging Environment,翻譯成中文叫做“集成開發(fā)環(huán)境”,在臺灣那邊叫做“整合開發(fā)環(huán)境”。
    2014-09-09
  • 出現(xiàn)module 'queue' has no attribute 'Queue'問題的解決

    出現(xiàn)module 'queue' has no attrib

    這篇文章主要介紹了出現(xiàn)module 'queue' has no attribute 'Queue'問題的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • Python?nonlocal關鍵字?與?global?關鍵字解析

    Python?nonlocal關鍵字?與?global?關鍵字解析

    這篇文章主要介紹了Python?nonlocal關鍵字?與?global?關鍵字解析,nonlocal關鍵字用來在函數(shù)或其他作用域中使用外層變量,global關鍵字用來在函數(shù)或其他局部作用域中使用全局變量,更多香瓜內容需要的小伙伴可以參考一下
    2022-03-03
  • Pygame實現(xiàn)小球躲避實例代碼

    Pygame實現(xiàn)小球躲避實例代碼

    大家好,本篇文章主要講的是Pygame實現(xiàn)小球躲避實例代碼,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12

最新評論