python3協(xié)程數(shù)量限制-多任務(wù)(3):協(xié)程_第1頁
python3協(xié)程數(shù)量限制-多任務(wù)(3):協(xié)程_第2頁
python3協(xié)程數(shù)量限制-多任務(wù)(3):協(xié)程_第3頁
python3協(xié)程數(shù)量限制-多任務(wù)(3):協(xié)程_第4頁
全文預(yù)覽已結(jié)束

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

python3協(xié)程數(shù)量限制_多任務(wù)(3):協(xié)程代碼環(huán)境:python3.6上?篇?章我們講了python中多線程的使?:點(diǎn)擊閱讀,現(xiàn)在我們講講python中的協(xié)程。異步IO我們知道,CPU速度遠(yuǎn)遠(yuǎn)快于磁盤、?絡(luò)等IO。在IO編程中,假如?個(gè)IO操作阻塞了當(dāng)前線程,會(huì)導(dǎo)致其他代碼?法執(zhí)?,所以我們使?多線程或者多進(jìn)程來并發(fā)執(zhí)?代碼。但是,系統(tǒng)資源是有限的,?旦線程數(shù)量過多,CPU的時(shí)間就花在線程切換上了,真正執(zhí)?代碼的時(shí)間下降,導(dǎo)致性能嚴(yán)重下降。針對(duì)這個(gè)問題,我們需要另?種解決?法:異步IO。異步IO,即當(dāng)代碼需要執(zhí)??個(gè)耗時(shí)的IO操作時(shí),它只發(fā)出IO指令,并不等待IO結(jié)果,然后就去執(zhí)?其他代碼了。?段時(shí)間后,當(dāng)IO返回結(jié)果時(shí),再通知CPU進(jìn)?處理。python中最初的協(xié)程了解最初的協(xié)程有助于我們理解后?現(xiàn)代協(xié)程的?法。協(xié)程這個(gè)概念并不是python?次提出的,?是從其他語?借鑒過來的。我們知道,兩個(gè)普通函數(shù)的調(diào)?是按順序的,?如A函數(shù)調(diào)?B函數(shù),B執(zhí)?完畢返回結(jié)果給A,A執(zhí)?完畢。協(xié)程看上去也是函數(shù),如果協(xié)程A調(diào)?協(xié)程B,在執(zhí)?過程中,協(xié)程B可以中斷,轉(zhuǎn)?執(zhí)?A,再在適當(dāng)?shù)臅r(shí)候返回B接著從中斷處往下執(zhí)?。協(xié)程的這種執(zhí)?特點(diǎn),恰好符合我們的需求:通過協(xié)程實(shí)現(xiàn)異步IO編程。?成器進(jìn)化成協(xié)程python基于generator進(jìn)??系列功能改進(jìn)后得到協(xié)程,語法上都是定義體中包含yield關(guān)鍵字。在協(xié)程中,yield不僅可以返回值,還能接收調(diào)?者通過.send()?法發(fā)出的參數(shù)。yield通常出現(xiàn)在表達(dá)式右邊,如:data=yieldsomething。如果yield后?沒有表達(dá)式,說明此時(shí)yield只負(fù)責(zé)接收數(shù)據(jù),協(xié)程始終返回None。簡(jiǎn)單協(xié)程的基本?為舉個(gè)簡(jiǎn)單例?:In[1]:defmy_coroutine():...:print('協(xié)程被激活')...:whileTrue:#yield后?不跟表達(dá)式,這?只接收send()傳過來的數(shù)據(jù)...:x=yield...:print(f'協(xié)程接收到參數(shù):{x}')...:In[2]:my_corou=my_coroutine()#可查看協(xié)程當(dāng)前狀態(tài)In[3]:frominspectimportgetgeneratorstateIn[4]:getgeneratorstate(my_corou)Out[4]:'GEN_CREATED'

#激活協(xié)程,此處可?my_corou.send(None)代替In[5]:next(my_corou)協(xié)程被激活I(lǐng)n[6]:getgeneratorstate(my_corou)Out[6]:'GEN_SUSPENDED'In[7]:return_value=my_corou.send(99)協(xié)程接收到參數(shù):99In[8]:print(return_value)NoneIn[9]:my_corou.close()In[10]:getgeneratorstate(my_corou)Out[10]:'GEN_CLOSED'通過例?我們主要了解的是,協(xié)程需要?動(dòng)激活才能真正調(diào)?,協(xié)程在不需要的時(shí)候要記得關(guān)閉。?協(xié)程改進(jìn)?產(chǎn)者-消費(fèi)者模型傳統(tǒng)?產(chǎn)者-消費(fèi)者模型中,?個(gè)線程寫消息,另?個(gè)線程取消息,通過鎖機(jī)制控制隊(duì)列和等待,但是?不??可能死鎖。如果改?協(xié)程,?產(chǎn)者?產(chǎn)消息后,直接通過yield跳轉(zhuǎn)到消費(fèi)者開始執(zhí)?,待消費(fèi)者執(zhí)?完畢后,再切換回?產(chǎn)者繼續(xù)?產(chǎn),整個(gè)流程?鎖且效率?:frominspectimportgetgeneratorstatedefconsumer():r='200OK'whileTrue:#yield接收?產(chǎn)者的數(shù)據(jù)賦值給n,并把處理結(jié)果狀態(tài)r返回n=yieldrprint(f'[CONSUMER]消費(fèi)了:{n}')defproducer(c):#別忘了激活協(xié)程c.send(None)n=0whilen<5:n=n+1print(f'[PRODUCER]?產(chǎn)了:{n}')#?旦?產(chǎn)了東西,通過c.send()切換到consumer執(zhí)?#consumer處理數(shù)據(jù)后通過yield返回結(jié)果狀態(tài),這?獲取返回內(nèi)容r=c.send(n)

print(f'[PRODUCER]消費(fèi)者返回的處理結(jié)果:{r}')print(f'?產(chǎn)者不?產(chǎn)了,看看當(dāng)前consumer狀態(tài):{getgeneratorstate(c)}')c.close()print(f'關(guān)閉consumer,看看當(dāng)前consumer狀態(tài):{getgeneratorstate(c)}')if__name__=="__main__":producer(consumer())上?例?整個(gè)流程只由?個(gè)線程執(zhí)?且?鎖,?產(chǎn)者和消費(fèi)者協(xié)作完成任務(wù),這種屬于協(xié)作式多任務(wù),跟多線程這種搶占式多任務(wù)要區(qū)分開。asyncio在python3.4版本中,開始引?標(biāo)準(zhǔn)庫asyncio直接內(nèi)置了對(duì)異步IO的?持。asyncio的編程模型就是?個(gè)消息循環(huán)。我們從asyncio模塊中直接獲取?個(gè)EventLoop的引?,然后把需要執(zhí)?的協(xié)程扔到EventLoop中執(zhí)?,就實(shí)現(xiàn)了異步IO。先簡(jiǎn)單介紹下asyncio涉及到的?些詞語:Future:?個(gè)對(duì)象,表?異步執(zhí)?的操作。通常情況下??不應(yīng)該創(chuàng)建Future,?只能由并發(fā)框架如asyncio實(shí)例化。Task:在EventLoop中負(fù)責(zé)執(zhí)?協(xié)程的任務(wù),是Future的?類。換句話說,Task就是Future,但反過來不?定。下?是asyncio常?API:asyncio.get_event_loop():獲取?個(gè)EventLoop對(duì)象,?來運(yùn)?協(xié)程asyncio.iscoroutine(obj):判斷?個(gè)對(duì)象是否是協(xié)程。asyncio.sleep(delay):直接當(dāng)做是?個(gè)耗時(shí)多少秒的協(xié)程即可。asyncio.ensure_future(coro_or_future):?參是協(xié)程,則激活協(xié)程,返回?個(gè)Task對(duì)象;如果?參是Future,則將?參直接返回。asyncio.gather(coros_or_futures):按?參中協(xié)程的順序保存協(xié)程的執(zhí)?結(jié)果,?部分情況下使?。asyncio.wait(futures):對(duì)?gather,不?定按?參順序返回執(zhí)?結(jié)果。返回包含已完成和掛起的Task,可通過接收參數(shù)return_when選擇返回結(jié)果的時(shí)機(jī),按實(shí)際情況使?。我們將在下?結(jié)合新的關(guān)鍵字async/await來舉例說明。async/await為了簡(jiǎn)化使?和標(biāo)識(shí)異步IO,從python3.5版本開始引?新的語法糖async/await,?async把?個(gè)generator標(biāo)記為協(xié)程函數(shù),然后在協(xié)程內(nèi)部?await調(diào)?另?個(gè)協(xié)程實(shí)現(xiàn)異步操作。注意:?async標(biāo)記協(xié)程函數(shù),調(diào)?該函數(shù)時(shí)協(xié)程尚未激活,激活該函數(shù)可以?await或者yieldfrom,也可以通過ensure_future()或者AbstractEventLoop.create_task()調(diào)度執(zhí)?。舉個(gè)例?:fromasyncioimportsleepasaiosleep,gather,get_event_loopasyncdefcompute(x,y):print("計(jì)算%s+%s..."%(x,y))awaitaiosleep(1)returnx+y

asyncdefprint_sum(x,y):result=awaitcompute(x,y)print("%s+%s=%s"%(x,y,result))asyncdefcoro_main():'''?般我們會(huì)寫?個(gè)coroutine的main函數(shù),專門負(fù)責(zé)管理協(xié)程'''awaitgather(print_sum(1,2),print_sum(4,9))defmain():aioloop=get_event_loop()#內(nèi)部使?ensure_future()激活協(xié)程aioloop.run_until_complete(coro_main())aioloop.close()if__name__=="__main__":main()執(zhí)?結(jié)果:計(jì)算1+2...計(jì)算4+9...(暫停約1秒,實(shí)際輸出沒有這?)1+2=34+9=13觀察例?運(yùn)?結(jié)果,我們看到:當(dāng)協(xié)程開始計(jì)算1+2前還有?個(gè)耗時(shí)1秒的IO操作,當(dāng)前線程并未等待,?是去執(zhí)?其他協(xié)程計(jì)算4+9,實(shí)現(xiàn)了并發(fā)執(zhí)?。協(xié)程結(jié)果按gather?參的順序打印??偨Y(jié)?對(duì)CPU?速執(zhí)?和IO設(shè)備的龜速嚴(yán)重不匹配問題,我們?少要知道兩種解決?法:使?多進(jìn)程和多線程并發(fā)執(zhí)?代碼;使?異步IO執(zhí)?代碼。python協(xié)程是基

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論