Python?異之如何同時(shí)運(yùn)行多個(gè)協(xié)程詳解
正文
asyncio 的一個(gè)好處是我們可以同時(shí)運(yùn)行許多協(xié)程。這些協(xié)同程序可以在一個(gè)組中創(chuàng)建并存儲(chǔ),然后同時(shí)一起執(zhí)行。這可以使用 asyncio.gather() 函數(shù)來實(shí)現(xiàn)。
讓我們仔細(xì)看看。
1. 什么是 Asyncio gather()
asyncio.gather() 模塊函數(shù)允許調(diào)用者將多個(gè)可等待對(duì)象組合在一起。分組后,可等待對(duì)象可以并發(fā)執(zhí)行、等待和取消。
它是一個(gè)有用的實(shí)用函數(shù),可用于分組和執(zhí)行多個(gè)協(xié)程或多個(gè)任務(wù)。
... # run a collection of awaitables results = await asyncio.gather(coro1(), asyncio.create_task(coro2()))
在我們可能預(yù)先創(chuàng)建許多任務(wù)或協(xié)程然后希望一次執(zhí)行它們并等待它們?nèi)客瓿珊笤倮^續(xù)的情況下,我們可以使用 asyncio.gather() 函數(shù)。
這是一種可能的情況,其中需要許多類似任務(wù)的結(jié)果,例如具有不同數(shù)據(jù)的相同任務(wù)或協(xié)程。
可等待對(duì)象可以并發(fā)執(zhí)行,返回結(jié)果,并且主程序可以通過使用它所依賴的結(jié)果來恢復(fù)。
gather() 函數(shù)比簡單地等待任務(wù)完成更強(qiáng)大。它允許將一組可等待對(duì)象視為單個(gè)可等待對(duì)象。
- 通過 await 表達(dá)式執(zhí)行并等待組中的所有可等待對(duì)象完成。
- 從所有分組的等待對(duì)象中獲取結(jié)果,稍后通過 result() 方法檢索。
- 要通過 cancel() 方法取消的一組等待對(duì)象。
- 通過 done() 方法檢查組中的所有可等待對(duì)象是否已完成。
- 僅當(dāng)組中的所有任務(wù)完成時(shí)才執(zhí)行回調(diào)函數(shù)。
2. 如何使用 Asyncio gather()
在本節(jié)中,我們將仔細(xì)研究如何使用 asyncio.gather() 函數(shù)。
asyncio.gather() 函數(shù)將一個(gè)或多個(gè)可等待對(duì)象作為參數(shù)。回想一下,可等待對(duì)象可能是協(xié)程、Future 或 Task。
因此,我們可以調(diào)用 gather() 函數(shù):
- 多項(xiàng)任務(wù)
- 多個(gè)協(xié)程
- 任務(wù)和協(xié)程的混合
... # execute multiple coroutines asyncio.gather(coro1(), coro2())
如果 Task 對(duì)象被提供給 gather(),它們將已經(jīng)在運(yùn)行,因?yàn)?Tasks 被安排為創(chuàng)建的一部分。asyncio.gather() 函數(shù)將可等待對(duì)象作為位置參數(shù)。
我們不能創(chuàng)建可等待對(duì)象的列表或集合并將其提供給收集,因?yàn)檫@會(huì)導(dǎo)致錯(cuò)誤。
... # cannot provide a list of awaitables directly asyncio.gather([coro1(), coro2()])
如果首先使用星號(hào)運(yùn)算符 (*) 將其解壓縮到單獨(dú)的表達(dá)式中,則可以提供等待列表。
... # gather with an unpacked list of awaitables asyncio.gather(*[coro1(), coro2()])
如果協(xié)程提供給 gather(),它們會(huì)自動(dòng)包裝在 Task 對(duì)象中。gather() 函數(shù)不會(huì)阻塞。
相反,它返回一個(gè)代表可等待對(duì)象組的 asyncio.Future 對(duì)象。
... # get a future that represents multiple awaitables group = asyncio.gather(coro1(), coro2())
一旦創(chuàng)建了 Future 對(duì)象,它就會(huì)在事件循環(huán)中自動(dòng)調(diào)度。awaitable 代表組,組中的所有 awaitable 都會(huì)盡快執(zhí)行。這意味著如果調(diào)用者什么都不做,那么預(yù)定的可等待對(duì)象組將運(yùn)行(假設(shè)調(diào)用者掛起)。
這也意味著您不必等待從 gather() 返回的 Future。
... # get a future that represents multiple awaitables group = asyncio.gather(coro1(), coro2()) # suspend and wait a while, the group may be executing.. await asyncio.sleep(10)
可以等待返回的 Future 對(duì)象,它將等待組中的所有可等待對(duì)象完成。
... # run the group of awaitables await group
等待從 gather() 返回的 Future 將返回可等待對(duì)象的返回值列表。
如果可等待對(duì)象沒有返回值,則此列表將包含默認(rèn)的“無”返回值。
... # run the group of awaitables and get return values results = await group
這通常在一行中執(zhí)行。
... # run tasks and get results on one line results = await asyncio.gather(coro1(), coro2())
3. 列表中多個(gè)協(xié)程的 gather() 示例
預(yù)先創(chuàng)建多個(gè)協(xié)程然后再收集它們是很常見的。這允許程序準(zhǔn)備要并發(fā)執(zhí)行的任務(wù),然后立即觸發(fā)它們的并發(fā)執(zhí)行并等待它們完成。
我們可以手動(dòng)或使用列表理解將許多協(xié)程收集到一個(gè)列表中。
... # create many coroutines coros = [task_coro(i) for i in range(10)]
然后我們可以用列表中的所有協(xié)程調(diào)用 gather()。協(xié)程列表不能直接提供給 gather() 函數(shù),因?yàn)檫@會(huì)導(dǎo)致錯(cuò)誤。相反,gather() 函數(shù)要求將每個(gè)可等待對(duì)象作為單獨(dú)的位置參數(shù)提供。
這可以通過將列表展開為單獨(dú)的表達(dá)式并將它們傳遞給 gather() 函數(shù)來實(shí)現(xiàn)。星號(hào)運(yùn)算符 (*) 將為我們執(zhí)行此操作。
... # run the tasks await asyncio.gather(*coros)
將它們結(jié)合在一起,下面列出了使用 gather() 運(yùn)行預(yù)先準(zhǔn)備好的協(xié)程列表的完整示例。
# SuperFastPython.com # example of gather for many coroutines in a list import asyncio # coroutine used for a task async def task_coro(value): # report a message print(f'>task {value} executing') # sleep for a moment await asyncio.sleep(1) # coroutine used for the entry point async def main(): # report a message print('main starting') # create many coroutines coros = [task_coro(i) for i in range(10)] # run the tasks await asyncio.gather(*coros) # report a message print('main done') # start the asyncio program asyncio.run(main())
運(yùn)行該示例會(huì)執(zhí)行 main() 協(xié)程作為程序的入口點(diǎn)。main() 協(xié)程然后使用列表理解創(chuàng)建一個(gè)包含 10 個(gè)協(xié)程對(duì)象的列表。然后將此列表提供給 gather() 函數(shù),并使用星號(hào)運(yùn)算符將其解壓縮為 10 個(gè)單獨(dú)的表達(dá)式。
然后 main() 協(xié)程等待從調(diào)用 gather() 返回的 Future 對(duì)象,暫停并等待所有調(diào)度的協(xié)程完成它們的執(zhí)行。協(xié)程會(huì)盡快運(yùn)行,報(bào)告它們獨(dú)特的消息并在終止前休眠。
只有在組中的所有協(xié)程都完成后,main() 協(xié)程才會(huì)恢復(fù)并報(bào)告其最終消息。這突出了我們?nèi)绾螠?zhǔn)備協(xié)程集合并將它們作為單獨(dú)的表達(dá)式提供給 gather() 函數(shù)。
main starting
>task 0 executing
>task 1 executing
>task 2 executing
>task 3 executing
>task 4 executing
>task 5 executing
>task 6 executing
>task 7 executing
>task 8 executing
>task 9 executing
main done
以上就是Python 異之如何同時(shí)運(yùn)行多個(gè)協(xié)程詳解的詳細(xì)內(nèi)容,更多關(guān)于Python 異步同時(shí)運(yùn)行多個(gè)協(xié)程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python向Excel中插入圖片的簡單實(shí)現(xiàn)方法
這篇文章主要介紹了Python向Excel中插入圖片的簡單實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了Python使用XlsxWriter模塊操作Excel單元格插入jpg格式圖片的相關(guān)操作技巧,非常簡單實(shí)用,需要的朋友可以參考下2018-04-04python打印n位數(shù)“水仙花數(shù)”(實(shí)例代碼)
這篇文章主要介紹了python打印n位數(shù)“水仙花數(shù)”,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-12-12python 監(jiān)聽salt job狀態(tài),并任務(wù)數(shù)據(jù)推送到redis中的方法
今天小編就為大家分享一篇python 監(jiān)聽salt job狀態(tài),并任務(wù)數(shù)據(jù)推送到redis中的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-01-01Python數(shù)據(jù)分析之分析千萬級(jí)淘寶數(shù)據(jù)
網(wǎng)購已經(jīng)成為人們生活不可或缺的一部分,本次項(xiàng)目基于淘寶app平臺(tái)數(shù)據(jù),通過相關(guān)指標(biāo)對(duì)用戶行為進(jìn)行分析,從而探索用戶相關(guān)行為模式。感興趣的可以學(xué)習(xí)一下2022-03-03Django如何自定義model創(chuàng)建數(shù)據(jù)庫索引的順序
這篇文章主要介紹了Django如何自定義model創(chuàng)建數(shù)據(jù)庫索引的順序,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-06-06python動(dòng)態(tài)網(wǎng)頁批量爬取
這篇文章主要介紹了python動(dòng)態(tài)網(wǎng)頁批量爬取的方法,主要針對(duì)四六級(jí)成績批量爬取,感興趣的小伙伴們可以參考一下2016-02-02使用 Python 列出串口的實(shí)現(xiàn)方法
有時(shí)在編程時(shí),我們需要獲取有關(guān)系統(tǒng)中可用通信端口的信息, 我們將討論如何使用 Python 來做到這一點(diǎn),將討論使用串口或 com 端口的通信, 我們將深入探索 Python 包,以幫助我們獲得系統(tǒng)的可用通信端口,感興趣的朋友一起看看吧2023-08-08