Pyhon之深入理解asyncio(二)

Asyncio.gather vs asyncio.wait

在上篇文章已經看到多次用 asyncio.gather了,還有另外一個用法是 asyncio.wait,他們都可以讓多個協程併發執行。那爲什麼提供2個方法呢?他們有什麼區別,適用場景是怎麼樣的呢?其實我之前也是有點困惑,直到我讀了asyncio的源碼。我們先看2個協程的例子:



在IPython裏面用gather執行一下:


Ok, asyncio.gather方法的名字說明了它的用途,gather的意思是「蒐集」,也就是能夠收集協程的結果,而且要注意,它會按輸入協程的順序保存的對應協程的執行結果。

接着我們說 asyncio.await,先執行一下:



asyncio.wait的返回值有2項,第一項表示完成的任務列表(done),第二項表示等待(Future)完成的任務列表(pending),每個任務都是一個Task實例,由於這2個任務都已經完成,所以可以執行 task.result()獲得協程返回值。

Ok, 說到這裏,我總結下它倆的區別的第一層區別:

asyncio.gather封裝的Task全程黑盒,只告訴你協程結果。
asyncio.wait會返回封裝的Task(包含已完成和掛起的任務),如果你關注協程執行結果你需要從對應Task實例裏面用result方法自己拿。
爲什麼說「第一層區別」, asyncio.wait看名字可以理解爲「等待」,所以返回值的第二項是pending列表,但是看上面的例子,pending是空集合,那麼在什麼情況下,pending裏面不爲空呢?這就是第二層區別: asyncio.wait支持選擇返回的時機。

asyncio.wait支持一個接收參數 return_when,在默認情況下, asyncio.wait會等待全部任務完成(returnwhen='ALLCOMPLETED'),它還支持FIRSTCOMPLETED(第一個協程完成就返回)和FIRSTEXCEPTION(出現第一個異常就返回):



看到了吧,這次只有協程b完成了,協程a還是pending狀態。

在大部分情況下,用asyncio.gather是足夠的,如果你有特殊需求,可以選擇asyncio.wait,舉2個例子:

需要拿到封裝好的Task,以便取消或者添加成功回調等
業務上需要FIRSTCOMPLETED/FIRSTEXCEPTION即返回的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章