Python循環(huán)體內(nèi)實(shí)現(xiàn)異步并發(fā)

問題起源:循環(huán)體內(nèi)無法實(shí)現(xiàn)異步。

Python使用異步模塊Asyncio實(shí)現(xiàn)多線程并發(fā),一般方式是:

async def func():
    # code...
    
async def main():
    await(func())

if __name__ =='__main__':
    asyncio.run(main())

但實(shí)驗(yàn)過程中有個(gè)需求,是讓循環(huán)體的每次循環(huán)都作為一個(gè)并發(fā)線程產(chǎn)生并發(fā)。

這種情況下,每次循環(huán)使用await調(diào)用異步函數(shù),無法實(shí)現(xiàn)需求中的并發(fā)需求。

asyncio程序如下:

import time
import asyncio

async def hello():
    await asyncio.sleep(1)
    print('Hello World:%s' % time.time())

async def main():
    start = time.time()
    for i in range(5):
        await(hello())
    print("use time: %f s" % (time.time()-start))

if __name__ =='__main__':
    asyncio.run(main())

程序結(jié)果:

Hello World:1608368438.992576
Hello World:1608368439.9939594
Hello World:1608368440.9950461
Hello World:1608368441.9971309
Hello World:1608368443.00034
use time: 5.008629 s

程序運(yùn)行時(shí)間是5秒,意味著并未達(dá)到異步的效果。

原因:整個(gè)for循環(huán)體是一個(gè)協(xié)程,協(xié)程切換時(shí)會(huì)掛起整個(gè)main協(xié)程。

解決辦法:使用asyncio.gather()

asyncio.gather()需要輸入一個(gè)任務(wù)列表,gather會(huì)劃分任務(wù),并分組執(zhí)行,因此可以應(yīng)對for循環(huán)體內(nèi)的異步。

完善后的代碼:

import time
import asyncio

async def hello():
    await asyncio.sleep(1)
    print('Hello World:%s' % time.time())

async def main():
    tasks=[]
    for i in range(5):
        tasks.append(hello())
    await asyncio.gather(*tasks)

if __name__ =='__main__':
    asyncio.run(main())

程序運(yùn)行結(jié)果:

Hello World:1608368546.8756351
Hello World:1608368546.8756351
Hello World:1608368546.8756351
Hello World:1608368546.8756351
Hello World:1608368546.8756351
use time: 1.002837 s

程序運(yùn)行時(shí)間是1秒,說明已經(jīng)達(dá)到異步效果。

參考:

異步編程 101:asyncio中的 for 循環(huán)

python中的asyncio使用詳解

Python中的asyncio代碼詳解

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容