摘要:第二節(jié)將任務(wù)添加到隊列上一個栗子只是簡單實現(xiàn)了下網(wǎng)頁與后臺的通信你可以在這里處理任何你想要的操作你已經(jīng)點到我了但由于是同一個進(jìn)程,如果你做了很耗時的操作,比如下載一張圖片之類的操作你會發(fā)現(xiàn),窗口卡住了,一般表現(xiàn)為窗口泛白,出現(xiàn)未響應(yīng)的提示但
第二節(jié) 將任務(wù)添加到隊列!
上一個栗子只是簡單實現(xiàn)了下網(wǎng)頁與后臺的通信
def clickMe(self): #你可以在這里處理任何你想要的操作 self.call_function("clickCallBack","你已經(jīng)點到我了!")
但由于是同一個進(jìn)程,如果你做了很耗時的操作,比如下載一張圖片之類的IO操作......
你會發(fā)現(xiàn),窗口卡住了,一般表現(xiàn)為窗口泛白,出現(xiàn)未響應(yīng)的提示......但這并不是程序真的未響應(yīng)了,等圖片下載完就會恢復(fù)原樣。
但是,你能接受嗎?
如果能的話......下面就可以不用看了,我說真的。
咳...嗯
繼續(xù)
為了不卡,我選擇了多進(jìn)程的方式,多線程也可以,但萬一這個線程死掉,會拉著主線程下水......以防萬一,我選擇再開一個進(jìn)程作為服務(wù)進(jìn)程。
from multiprocessing import Process,Queue # 創(chuàng)建用于接收服務(wù)進(jìn)程傳遞的回饋任務(wù)的隊列,此隊列線程安全 self.GuiQueue = Queue() # 創(chuàng)建用于接收界面進(jìn)程發(fā)送的任務(wù)的隊列,此隊列線程安全 self.ServiceQueue = Queue() p = Process(target = startServiceP, args = ( self.GuiQueue, self.ServiceQueue )) p.daemon = True #設(shè)置為守護(hù)進(jìn)程,保證主進(jìn)程退出時子進(jìn)程也會退出 p.start()
為何選用Process及Queue?
單純開啟一個子進(jìn)程或許還有一個更好的選擇:Popen,它可以啟動獨立的py腳本作為子進(jìn)程,也有很多方法可供選擇。但我不知道應(yīng)該如何通信及傳參,找了一些栗子,無奈無法完全理解,只能待日后解決。
Python多進(jìn)程通信方法有Queue、Pipe、Value、Array
pipe用來在兩個進(jìn)程間通信
queue用來在多個進(jìn)程間實現(xiàn)通信
Value + Array 是python中共享內(nèi)存映射文件的方法
最初的設(shè)計比現(xiàn)在復(fù)雜,共有3個進(jìn)程,故棄用pipe
Value + Array的方式當(dāng)時沒找到,遺漏
只剩Queue......
據(jù)說Queue速度上慢一些,但以咱目前的水平,速度不是瓶頸
夠用就行,不是嗎?
pipe后期也會研究的就是了......
我們來看一下這個服務(wù)進(jìn)程有些啥
def startServiceP(_GuiQueue, _ServiceQueue): """開啟一個服務(wù)進(jìn)程""" funMap = ServiceEvent( _GuiQueue ) EventManager( _ServiceQueue, funMap ).Start()
就這么簡單~
funMap 是啥? ServiceEvent 又哪來的!? EventManager 又是什么鬼??!!
等下,把刀放下......
咳...
一般來說,從界面?zhèn)鱽淼拿疃际亲址?,然后通過這個字符串來執(zhí)行指定函數(shù)
funMap 就是存放的事先寫好的函數(shù)字典
看一下ServiceEvent():
class ServiceEvent(object): """服務(wù)進(jìn)程""" def __init__(self, _GuiQueue): self.GuiQueue = _GuiQueue def clickCallBack(self, msg): sleep(3) self.__putGui( "clickCallBack", msg ) def __putGui(self, f, m = None ): self.GuiQueue.put({ "fun" : f, "msg" : m })
現(xiàn)在可以調(diào)用 funMap.clickCallBack()
關(guān)于 GuiQueue 等會再說,先來看一下EventManager()
clickMe() 只是把要執(zhí)行的任務(wù)發(fā)送給 ServiceQueue 了,但此任務(wù)不會自動執(zhí)行,我們還需要一個循環(huán)來讀取任務(wù),這就是EventManager()的功能。
EventManager()核心代碼:
def __Run(self): while self.__active == True: try: # 獲取事件的阻塞時間設(shè)為1秒 event = self.Queue.get(timeout = 1) getattr( self.funMap, event["fun"] )( event["msg"] ) #關(guān)鍵代碼 except Exception as e: pass
以上是服務(wù)進(jìn)程的相關(guān)內(nèi)容,我們再回來看一下界面該如何及時獲得反饋
from threading import Thread t = Thread(target = queueLoop, args=( self.GuiQueue, self.call_function )) t.daemon = True t.start()
嗯,此處我開了另一個線程來執(zhí)行這個循環(huán),老實說沒想到特別好的辦法,這個循環(huán)肯定不能在主線程使用,會卡界面的,開一個進(jìn)程又太小題大做,折中方案,用了多線程,好在它只是遍歷Queue,沒啥復(fù)雜的操作......
def queueLoop( _GuiQueue, funCall ): guiCallBack = GuiCallBack( funCall ) EventManager( _GuiQueue, guiCallBack ).Start()
基本和服務(wù)進(jìn)程一樣,不做過多解釋了~
需要注意的只有 funCall這個參數(shù),很重要,界面的事件調(diào)用全靠它。
Tis:
$(.click-me).on("click",function(){ view.clickMe(); //view Sciter內(nèi)置的對象,所有tis都可調(diào)用 })
main.py :
# 導(dǎo)入sciter支持,必須安裝pysciter import sciter import ctypes import json from multiprocessing import Process,Queue from threading import Thread from EventManager import EventManager from FunManager import ServiceEvent, GuiCallBack # 設(shè)置dpi, 防止程序在高分屏下發(fā)虛 ctypes.windll.user32.SetProcessDPIAware(2) def startServiceP(_GuiQueue, _ServiceQueue): """開啟一個服務(wù)進(jìn)程""" funMap = ServiceEvent( _GuiQueue ) EventManager( _ServiceQueue, funMap ).Start() def queueLoop( _GuiQueue, funCall ): guiCallBack = GuiCallBack( funCall ) EventManager( _GuiQueue, guiCallBack ).Start() class Frame(sciter.Window): def __init__(self): """ ismain=False, ispopup=False, ischild=False, resizeable=True, parent=None, uni_theme=False, debug=True, pos=None, pos=(x, y) size=None """ super().__init__(ismain=True, debug=True) self.set_dispatch_options(enable=True, require_attribute=False) def _document_ready(self, target): """在文檔加載后執(zhí)行,如果設(shè)置啟動畫面,可以在這里結(jié)束""" # 創(chuàng)建用于接收服務(wù)進(jìn)程傳遞的回饋任務(wù)的隊列,此隊列線程安全 self.GuiQueue = Queue() # 創(chuàng)建用于接收界面進(jìn)程發(fā)送的任務(wù)的隊列,此隊列線程安全 self.ServiceQueue = Queue() p = Process(target = startServiceP, args = ( self.GuiQueue, self.ServiceQueue )) p.daemon = True #設(shè)置為守護(hù)進(jìn)程,保證主進(jìn)程退出時子進(jìn)程也會退出 p.start() t = Thread(target = queueLoop, args=( self.GuiQueue, self.call_function )) t.daemon = True t.start() def clickMe(self): # 點擊頁面上的按鈕后,只將任務(wù)添加到服務(wù)隊列,耗時很短,因此不會發(fā)生界面卡頓現(xiàn)象 self.__putService("clickCallBack","你已經(jīng)點到我了!") def __putService(self, f, m = None): """接收界面事件并轉(zhuǎn)發(fā)""" self.ServiceQueue.put({ "fun" : f, "msg" : m }) if __name__ == "__main__": frame = Frame() frame.load_file("Gui/main.html") frame.run_app()
EventManager.py:
class EventManager: def __init__(self, _Queue, funMap): self.__active = False self.Queue = _Queue self.funMap = funMap def __Run(self): while self.__active == True: try: # 獲取事件的阻塞時間設(shè)為1秒 event = self.Queue.get(timeout = 1) getattr( self.funMap, event["fun"] )( event["msg"] ) except Exception as e: pass def Start(self): self.__active = True self.__Run() def Stop(self): self.__active = False
FunManager.py:
from time import sleep class ServiceEvent(object): """服務(wù)進(jìn)程""" def __init__(self, _GuiQueue): self.GuiQueue = _GuiQueue def clickCallBack(self, msg): sleep(3) self.__putGui( "clickCallBack", msg ) def __putGui(self, f, m = None ): self.GuiQueue.put({ "fun" : f, "msg" : m }) class GuiCallBack(object): def __init__(self, funCall): self.funCall = funCall def clickCallBack(self, msg): return self.funCall("clickCallBack", msg )
代碼漸漸多了起來,但效果還是很讓人滿意的。
缺點是一不留神容易出錯
源碼
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/40773.html
摘要:第三節(jié)協(xié)程繼續(xù)基礎(chǔ)框架搭好了,下面來正式的來一個項目吧全球設(shè)計師的作品展示平臺就從這拉幾張圖吧,具體的網(wǎng)頁解析方式網(wǎng)上有很多,在此略過,我已經(jīng)取出了一些圖片地址,保存在了里,這次就用這些吧。 第三節(jié) 協(xié)程??? 繼續(xù)...基礎(chǔ)框架搭好了,下面來正式的來一個項目吧 behance 全球設(shè)計師的作品展示平臺 就從這拉幾張圖吧,具體的網(wǎng)頁解析方式網(wǎng)上有很多,在此略過,我已經(jīng)取出了一些圖片地址,...
摘要:下載地址簡介結(jié)合與編寫軟件使用方法安裝個人使用建立的環(huán)境下載并解壓下載并解壓打開控制臺轉(zhuǎn)到解壓目錄比如此時就會將安裝到第三方安裝包的目錄下我的是注冊或者修改源碼注冊方式找到位位使用控制臺注冊路徑使用絕對路徑可以復(fù)制到然后就可以了修改 下載地址: Pysciter-GitHub Sciter 簡介: 結(jié)合HTML與Python編寫軟件 使用方法: 安裝Python3 (個人使用A...
摘要:如何在中使用動畫前端掘金本文講一下中動畫應(yīng)用的部分。與的快速入門指南推薦前端掘金是非常棒的框架,能夠創(chuàng)建功能強(qiáng)大,動態(tài)功能的。自發(fā)布以來,已經(jīng)廣泛應(yīng)用于開發(fā)中。 如何在 Angular 中使用動畫 - 前端 - 掘金本文講一下Angular中動畫應(yīng)用的部分。 首先,Angular本生不提供動畫機(jī)制,需要在項目中加入Angular插件模塊ngAnimate才能完成Angular的動畫機(jī)制...
摘要:第四章安全管理制度發(fā)布第十條安全管理制度必須以正式文件的形式發(fā)布施行。第十一條安全管理制度由信息安全管理小組制訂,信息安全領(lǐng)導(dǎo)小組審批發(fā)布。第二十條安全管理制度的修改與廢止須經(jīng)信息安全領(lǐng)導(dǎo)組織審批確認(rèn),信息安全管理部門備案。 字?jǐn)?shù) 3610閱讀 760評論 0贊 3《xxxx安全管理制度匯編》****制度管理辦法****文...
閱讀 3682·2021-09-27 14:02
閱讀 1796·2019-08-30 15:56
閱讀 1749·2019-08-29 18:44
閱讀 3285·2019-08-29 17:21
閱讀 492·2019-08-26 17:15
閱讀 1180·2019-08-26 13:57
閱讀 1248·2019-08-26 13:56
閱讀 2889·2019-08-26 11:30