1. 程式人生 > >對python async與await的理解

對python async與await的理解

重新 消失 解釋 等待 yield 使用 tran 4.5 quest

async/await關鍵字是出現在python3.4以後。網上已經有很多文章對async/await這兩個關鍵字都有講解,包括如何由python2的yield from發展到async/await這兩個關鍵字,以及一些代碼實現都有。但是對於像我這樣初次接觸的人來說,光看代碼分析也不一定能理解,我也是在度娘上搜索很多相關的網站,當中也有官網,都沒有發現能讓我一眼看懂在什麽地方可以用await,什麽情況用await的文章。經過自己的重新思考,總算對async、await有一些初步的了解,所以想把自己的理解記錄下來,希望對一些學習協程或者異步的初學者也有一定的幫助。

對於網上能搜到的一些代碼實現、例子,這裏就不重復了。

一、首先要知道什麽是協程、異步。

舉個例子:假設有1個洗衣房,裏面有10臺洗衣機,有一個洗衣工在負責這10臺洗衣機。那麽洗衣房就相當於1個進程,洗衣工就相當1個線程。如果有10個洗衣工,就相當於10個線程,1個進程是可以開多線程的。這就是多線程!

那麽協程呢?先不急。大家都知道,洗衣機洗衣服是需要等待時間的,如果10個洗衣工,1人負責1臺洗衣機,這樣效率肯定會提高,但是不覺得浪費資源嗎?明明1 個人能做的事,卻要10個人來做。只是把衣服放進去,打開開關,就沒事做了,等衣服洗好再拿出來就可以了。就算很多人來洗衣服,1個人也足以應付了,開好第一臺洗衣機,在等待的時候去開第二臺洗衣機,再開第三臺,……直到有衣服洗好了,就回來把衣服取出來,接著再取另一臺的(哪臺洗好先就取哪臺,所以協程是無序的)。這就是計算機的協程!洗衣機就是執行的方法。

當你程序中方法需要等待時間的話,就可以用協程,效率高,消耗資源少。

好了!現在來總結一下:

洗衣房 ==> 進程

洗衣工 ==> 線程

洗衣機 ==> 方法(函數)

二、async\await 的使用

正常的函數在執行時是不會中斷的,所以你要寫一個能夠中斷的函數,就需要添加async關鍵。

async 用來聲明一個函數為異步函數,異步函數的特點是能在函數執行過程中掛起,去執行其他異步函數,等到掛起條件(假設掛起條件是sleep(5))消失後,也就是5秒到了再回來執行。

await 用來用來聲明程序掛起,比如異步程序執行到某一步時需要等待的時間很長,就將此掛起,去執行其他的異步程序。await 後面只能跟異步程序或有__await__屬性的對象,因為異步程序與一般程序不同。假設有兩個異步函數async a,async b,a中的某一步有await,當程序碰到關鍵字await b()後,異步程序掛起後去執行另一個異步b程序,就是從函數內部跳出去執行其他函數,當掛起條件消失後,

不管b是否執行完,要馬上從b程序中跳出來,回到原程序執行原來的操作。如果await後面跟的b函數不是異步函數,那麽操作就只能等b執行完再返回,無法在b執行的過程中返回。如果要在b執行完才返回,也就不需要用await關鍵字了,直接調用b函數就行。所以這就需要await後面跟的是異步函數了。在一個異步函數中,可以不止一次掛起,也就是可以用多個await。

三、實例:

 1 async def test2(i):
 2     r = await other_test(i)
 3     print(i,r)
 4 
 5 async def other_test(i):
 6     r = requests.get(i)
 7     print(i)
 8     await asyncio.sleep(4)
 9     print(time.time()-start)
10     return r
11 
12 url = ["https://segmentfault.com/p/1210000013564725",
13        "https://www.jianshu.com/p/83badc8028bd",
14        "https://www.baidu.com/"]
15 
16 loop = asyncio.get_event_loop()
17 task = [asyncio.ensure_future(test2(i)) for i in url]
18 start = time.time()
19 20 loop.run_until_complete(asyncio.wait(task))
21 endtime = time.time()-start
22 print(endtime)
23 loop.close()

輸出結果:

 1 https://segmentfault.com/p/1210000013564725
 2 https://www.jianshu.com/p/83badc8028bd
 3 https://www.baidu.com/
 4 4.425147771835327
 5 https://segmentfault.com/p/1210000013564725 <Response [200]>
 6 4.5975635051727295
 7 https://www.jianshu.com/p/83badc8028bd <Response [403]>
 8 4.722797632217407
 9 https://www.baidu.com/ <Response [200]>
10 4.722797632217407

對於下面這幾行代碼:

loop = asyncio.get_event_loop()
task = [asyncio.ensure_future(test2(i)) for i in url]
loop.run_until_complete(asyncio.wait(task))
loop.close()
可以在網上找到具體講解,在這可用下圖來粗略形容一下
技術分享圖片
當所有的異步程序運行完就會返回最後結果。
對於什麽是task和future,asyncio.wait()與asyncio.gather()、asyncio.ensure_future()這些大家可以網上找到解釋。

說到這裏,相信你也大概清楚在什麽時候用async、什麽時候await了吧! 如果有說得不對的地方,請多多指正!!

技術分享圖片 技術分享圖片 技術分享圖片

對python async與await的理解