国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Python3結(jié)合Sciter編寫桌面程序第三節(jié)

fobnn / 2608人閱讀

摘要:第三節(jié)協(xié)程繼續(xù)基礎(chǔ)框架搭好了,下面來正式的來一個(gè)項(xiàng)目吧全球設(shè)計(jì)師的作品展示平臺就從這拉幾張圖吧,具體的網(wǎng)頁解析方式網(wǎng)上有很多,在此略過,我已經(jīng)取出了一些圖片地址,保存在了里,這次就用這些吧。

第三節(jié) 協(xié)程???

繼續(xù)...基礎(chǔ)框架搭好了,下面來正式的來一個(gè)項(xiàng)目吧

behance

全球設(shè)計(jì)師的作品展示平臺

就從這拉幾張圖吧,具體的網(wǎng)頁解析方式網(wǎng)上有很多,在此略過,我已經(jīng)取出了一些圖片地址,保存在了list.txt里,這次就用這些吧。

綜合多種因素,最后選用了協(xié)程來下載圖片

asyncio

框架則用了aiohttp

實(shí)現(xiàn)思路:

目的

將網(wǎng)絡(luò)上的圖片(最好是縮略圖)先下載到本地,記錄圖片信息,比如ID以便獲得更高質(zhì)量的圖片,將圖片顯示到界面

問題

為了更快速的展示頁面,我需要同時(shí)下載一定數(shù)量的圖片...

我需要?jiǎng)討B(tài)的將下載任務(wù)發(fā)送給后臺服務(wù)...

這里可以在程序啟動的時(shí)候設(shè)置一個(gè)配置列表cfg

from os import path as osPath, getcwd, mkdir
...
def __init__(self):
    ...
    self.cfg = self.initCfg()

def initCfg(self):
        cfg = {}
        # 代理,沒有可不用設(shè)置
        # cfg["proxies"] = "127.0.0.1:61274"
        # 加載圖片列表
        filename = "list.txt"
        if osPath.exists(filename):
            with open(filename, "r") as f:
                cfg["picList"] = f.read().strip().split("
")
        # 設(shè)置圖片的保存位置
        current_folder = getcwd()
        cfg["pic_temp"] = osPath.join( current_folder, "pic_temp")
        if not osPath.isdir( cfg["pic_temp"] ):
            mkdir(cfg["pic_temp"])
        return cfg

然后傳遞給服務(wù)進(jìn)程就可以了

p = Process(target = startServiceP, args = ( self.GuiQueue, self.ServiceQueue, self.cfg ))

先來修改一下html的內(nèi)容,添加一個(gè)自定義控件,用來存放圖片:


    
    

在服務(wù)進(jìn)程ServiceEvent里添加一個(gè)方法getPicByList()

def getPicByList(self, msg):
        # 為圖片創(chuàng)建占位圖
        imgidList = self.__creatPlaceholderImg()
        for imgid in imgidList:
            picHttp = self.cfg["picList"].pop(0)
            file_name = picHttp.split("/")[-1]
            file_path = osPath.join( self.cfg["pic_temp"], file_name )
            # 圖片下載完成后需要執(zhí)行的任務(wù)
            _GuiRecvMsgDict = {
                "fun" : "setImgBg",
                "msg" : {"id":imgid,"fpath":file_path}
            }
            if not osPath.isfile(file_path):
                # 將下載任務(wù)動態(tài)添加到協(xié)程循環(huán)中
                self.__run_coroutine_threadsafe(
                    {"id": imgid,"http": picHttp,"fpath": file_path},
                    _GuiRecvMsgDict
                )
            else:
                self.__putGui( "setImgBg", {"id":imgid,"fpath":file_path} )

當(dāng)用戶點(diǎn)擊下載圖片的按鈕后會執(zhí)行到這個(gè)方法,為了更好的體驗(yàn),在圖片下載之前先為其占據(jù)了空間,可以在其上顯示loading動畫,更重要的一點(diǎn)是,通過它可以控制圖片的顯示順序,因?yàn)橛脜f(xié)程下載圖片,你無法預(yù)知完成的順序...

def __creatPlaceholderImg(self):
        # 先創(chuàng)建5個(gè)占位圖
        html = ""
        imgidList = []
        time_now = ""
        for i in range(0, 5):
            time_now = "-".join( ( str(i), str(time()) ) )
            # 儲存圖片的id
            imgidList.append( time_now )
            html += self.html % ( time_now )
        self.__putGui("creatPlaceholderImg", html)
        return imgidList

之后就到了動態(tài)創(chuàng)建協(xié)程的部分了

def __run_coroutine_threadsafe(self, data, _GuiRecvMsgDict):
        asyncio.run_coroutine_threadsafe(self.dld.stream_download(
            data,
            _GuiRecvMsgDict
        ), self.new_loop)

但在正式介紹run_coroutine_threadsafe()之前,我們需要先開啟一個(gè)協(xié)程循環(huán)

但我們已經(jīng)開啟了一個(gè)用于處理隊(duì)列的循環(huán)了,沒辦法再開一個(gè)(也不排除是咱太菜),于是另開了一個(gè)線程專來處理協(xié)程

class ServiceEvent(object):
    """服務(wù)進(jìn)程"""
    def __init__(self, _GuiQueue, cfg):
        ...
        # 主線程中創(chuàng)建一個(gè)事件循環(huán)
        self.new_loop = asyncio.new_event_loop()
        self.dld = AsyncioDownload( self.new_loop, self.GuiQueue, self.proxies )
class AsyncioDownload(object):
    """使用協(xié)程下載圖片"""
    def __init__(self, loop, _GuiRecvMsg, proxies=None ):
        self.GuiRecvMsg = _GuiRecvMsg
        self._session = None
        self.loop = loop
        self.prox = "".join(("http://", proxies)) if proxies else proxies
        self.timeout = 10
        # 啟動一個(gè)線程,傳遞主線程中創(chuàng)建的事件循環(huán)
        t = Thread(target=self.start_loop, args=(self.loop,))
        t.setDaemon(True)    # 設(shè)置子線程為守護(hù)線程
        t.start()

    def start_loop(self, loop):
        # 啟動事件循環(huán)
        asyncio.set_event_loop(loop)
        loop.run_forever()

    def __session(self):
        if self._session is None:
            self._session = aiohttp.ClientSession(loop=self.loop)
        return self._session

    async def stream_download(self, d, _GuiRecvMsgDict):
        try:
            client = self.__session()
            async with client.get( d["http"], proxy=self.prox, timeout=self.timeout) as response:
                if response.status != 200:
                    print("error")
                    return
                # 保存圖片到本地
                if not osPath.isfile(d["fpath"]):
                    with open(d["fpath"], "ab") as file:
                        while True:
                            chunk = await response.content.read(1024)
                            if not chunk:
                                break
                            file.write(chunk)
                # 圖片下載完成后告知主線程
                self.GuiRecvMsg.put(_GuiRecvMsgDict)
        except asyncio.TimeoutError:
            pass

最后,主進(jìn)程獲得圖片的id及路徑,顯示到窗口中

function setImgBg( d ){
    var div = $(div[imgid="{d.id}"]);
    if(div){
        div.post( ::this.style#background-image = "url(" + d.fpath + ")" );
    }
}

源碼

總結(jié):

完成這個(gè)項(xiàng)目使用了

多進(jìn)程 ---- 后臺服務(wù)

多線程 ---- 事件循環(huán)

協(xié)程 ---- IO操作

相對一個(gè)單純的爬蟲腳本來說,還是有點(diǎn)復(fù)雜的,尤其是交互,難怪這么多人不愿意寫界面...

雖然還有不足,但本次項(xiàng)目的內(nèi)容就到這了。

謝謝。

云服務(wù)器 GPU云服務(wù)器 第三節(jié) webrtc結(jié)合electron桌面分享 Sciter 安卓程序編寫

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/40761.html

相關(guān)文章

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<