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

下載本文檔

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

文檔簡介

python3協(xié)程數(shù)量限制_多任務(3):協(xié)程代碼環(huán)境:python3.6上?篇?章我們講了python中多線程的使?:點擊閱讀,現(xiàn)在我們講講python中的協(xié)程。異步IO我們知道,CPU速度遠遠快于磁盤、?絡(luò)等IO。在IO編程中,假如?個IO操作阻塞了當前線程,會導致其他代碼?法執(zhí)?,所以我們使?多線程或者多進程來并發(fā)執(zhí)?代碼。但是,系統(tǒng)資源是有限的,?旦線程數(shù)量過多,CPU的時間就花在線程切換上了,真正執(zhí)?代碼的時間下降,導致性能嚴重下降。針對這個問題,我們需要另?種解決?法:異步IO。異步IO,即當代碼需要執(zhí)??個耗時的IO操作時,它只發(fā)出IO指令,并不等待IO結(jié)果,然后就去執(zhí)?其他代碼了。?段時間后,當IO返回結(jié)果時,再通知CPU進?處理。python中最初的協(xié)程了解最初的協(xié)程有助于我們理解后?現(xiàn)代協(xié)程的?法。協(xié)程這個概念并不是python?次提出的,?是從其他語?借鑒過來的。我們知道,兩個普通函數(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,再在適當?shù)臅r候返回B接著從中斷處往下執(zhí)?。協(xié)程的這種執(zhí)?特點,恰好符合我們的需求:通過協(xié)程實現(xiàn)異步IO編程。?成器進化成協(xié)程python基于generator進??系列功能改進后得到協(xié)程,語法上都是定義體中包含yield關(guān)鍵字。在協(xié)程中,yield不僅可以返回值,還能接收調(diào)?者通過.send()?法發(fā)出的參數(shù)。yield通常出現(xiàn)在表達式右邊,如:data=yieldsomething。如果yield后?沒有表達式,說明此時yield只負責接收數(shù)據(jù),協(xié)程始終返回None。簡單協(xié)程的基本?為舉個簡單例?:In[1]:defmy_coroutine():...:print('協(xié)程被激活')...:whileTrue:#yield后?不跟表達式,這?只接收send()傳過來的數(shù)據(jù)...:x=yield...:print(f'協(xié)程接收到參數(shù):{x}')...:In[2]:my_corou=my_coroutine()#可查看協(xié)程當前狀態(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é)程需要?動激活才能真正調(diào)?,協(xié)程在不需要的時候要記得關(guān)閉。?協(xié)程改進?產(chǎn)者-消費者模型傳統(tǒng)?產(chǎn)者-消費者模型中,?個線程寫消息,另?個線程取消息,通過鎖機制控制隊列和等待,但是?不??可能死鎖。如果改?協(xié)程,?產(chǎn)者?產(chǎn)消息后,直接通過yield跳轉(zhuǎn)到消費者開始執(zhí)?,待消費者執(zhí)?完畢后,再切換回?產(chǎn)者繼續(xù)?產(chǎn),整個流程?鎖且效率?:frominspectimportgetgeneratorstatedefconsumer():r='200OK'whileTrue:#yield接收?產(chǎn)者的數(shù)據(jù)賦值給n,并把處理結(jié)果狀態(tài)r返回n=yieldrprint(f'[CONSUMER]消費了:{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]消費者返回的處理結(jié)果:{r}')print(f'?產(chǎn)者不?產(chǎn)了,看看當前consumer狀態(tài):{getgeneratorstate(c)}')c.close()print(f'關(guān)閉consumer,看看當前consumer狀態(tài):{getgeneratorstate(c)}')if__name__=="__main__":producer(consumer())上?例?整個流程只由?個線程執(zhí)?且?鎖,?產(chǎn)者和消費者協(xié)作完成任務,這種屬于協(xié)作式多任務,跟多線程這種搶占式多任務要區(qū)分開。asyncio在python3.4版本中,開始引?標準庫asyncio直接內(nèi)置了對異步IO的?持。asyncio的編程模型就是?個消息循環(huán)。我們從asyncio模塊中直接獲取?個EventLoop的引?,然后把需要執(zhí)?的協(xié)程扔到EventLoop中執(zhí)?,就實現(xiàn)了異步IO。先簡單介紹下asyncio涉及到的?些詞語:Future:?個對象,表?異步執(zhí)?的操作。通常情況下??不應該創(chuàng)建Future,?只能由并發(fā)框架如asyncio實例化。Task:在EventLoop中負責執(zhí)?協(xié)程的任務,是Future的?類。換句話說,Task就是Future,但反過來不?定。下?是asyncio常?API:asyncio.get_event_loop():獲取?個EventLoop對象,?來運?協(xié)程asyncio.iscoroutine(obj):判斷?個對象是否是協(xié)程。asyncio.sleep(delay):直接當做是?個耗時多少秒的協(xié)程即可。asyncio.ensure_future(coro_or_future):?參是協(xié)程,則激活協(xié)程,返回?個Task對象;如果?參是Future,則將?參直接返回。asyncio.gather(coros_or_futures):按?參中協(xié)程的順序保存協(xié)程的執(zhí)?結(jié)果,?部分情況下使?。asyncio.wait(futures):對?gather,不?定按?參順序返回執(zhí)?結(jié)果。返回包含已完成和掛起的Task,可通過接收參數(shù)return_when選擇返回結(jié)果的時機,按實際情況使?。我們將在下?結(jié)合新的關(guān)鍵字async/await來舉例說明。async/await為了簡化使?和標識異步IO,從python3.5版本開始引?新的語法糖async/await,?async把?個generator標記為協(xié)程函數(shù),然后在協(xié)程內(nèi)部?await調(diào)?另?個協(xié)程實現(xiàn)異步操作。注意:?async標記協(xié)程函數(shù),調(diào)?該函數(shù)時協(xié)程尚未激活,激活該函數(shù)可以?await或者yieldfrom,也可以通過ensure_future()或者AbstractEventLoop.create_task()調(diào)度執(zhí)?。舉個例?:fromasyncioimportsleepasaiosleep,gather,get_event_loopasyncdefcompute(x,y):print("計算%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():'''?般我們會寫?個coroutine的main函數(shù),專門負責管理協(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é)果:計算1+2...計算4+9...(暫停約1秒,實際輸出沒有這?)1+2=34+9=13觀察例?運?結(jié)果,我們看到:當協(xié)程開始計算1+2前還有?個耗時1秒的IO操作,當前線程并未等待,?是去執(zhí)?其他協(xié)程計算4+9,實現(xiàn)了并發(fā)執(zhí)?。協(xié)程結(jié)果按gather?參的順序打印。總結(jié)?對CPU?速執(zhí)?和IO設(shè)備的龜速嚴重不匹配問題,我們?少要知道兩種解決?法:使?多進程和多線程并發(fā)執(zhí)?代碼;使?異步IO執(zhí)?代碼。python協(xié)程是基

溫馨提示

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

評論

0/150

提交評論