溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python中asyncio庫-線程并發函數的案例分析

發布時間:2020-08-03 10:25:18 來源:億速云 閱讀:220 作者:清晨 欄目:編程語言

這篇文章主要介紹Python中asyncio庫-線程并發函數的案例分析,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

Asyncio ——gather vs wait

在Asyncio中不止可以多次使用asyncio.gather,還有另外一個用法是asyncio.wait,他們都可以讓多個協程并發執行。

Python中asyncio庫-線程并發函數的案例分析

那為什么提供2個方法呢?他們有什么區別,適用場景是怎么樣的呢?我們先看2個協程的例子:

async def a():
    print('Suspending a')
    await asyncio.sleep(3)
    print('Resuming a')
    return 'A'
async def b():
    print('Suspending b')
    await asyncio.sleep(1)
    print('Resuming b')
    return 'B'

在IPython里面用gather執行一下:

In : return_value_a, return_value_b = await asyncio.gather(a(), b())
Suspending a
Suspending b
Resuming b
Resuming a
In : return_value_a, return_value_b
Out: ('A', 'B')

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

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

In : done, pending = await asyncio.wait([a(), b()])
Suspending b
Suspending a
Resuming b
Resuming a
In : done
Out:
{<Task finished coro=<a() done, defined at <ipython-input-5-5ee142734d16>:1> result='A'>,
 <Task finished coro=<b() done, defined at <ipython-input-5-5ee142734d16>:8> result='B'>}
In : pending
Out: set()
In : task = list(done)[0]
In : task
Out: <Task finished coro=<b() done, defined at <ipython-input-5-5ee142734d16>:8> result='B'>
In : task.result()
Out: 'B'

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會等待全部任務完成(return_when='ALL_COMPLETED'),它還支持FIRST_COMPLETED(第一個協程完成就返回)和FIRST_EXCEPTION(出現第一個異常就返回):

In : done, pending = await asyncio.wait([a(), b()], return_when=asyncio.tasks.FIRST_COMPLETED)
Suspending a
Suspending b
Resuming b
In : done
Out: {<Task finished coro=<b() done, defined at <ipython-input-5-5ee142734d16>:8> result='B'>}
In : pending
Out: {<Task pending coro=<a() running at <ipython-input-5-5ee142734d16>:3> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x108065e58>()]>>}

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

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

需要拿到封裝好的Task,以便取消或者添加成功回調等

業務上需要FIRST_COMPLETED/FIRST_EXCEPTION即返回的

asyncio.create_task vs loop.create_task vs asyncio.ensure_future

創建一個Task一共有3種方法,如這小節的標題。在上篇文章我說過,從Python 3.7開始可以統一的使用更高階的asyncio.create_task。其實asyncio.create_task就是用的loop.create_task:

def create_task(coro):
    loop = events.get_running_loop()
    return loop.create_task(coro)

loop.create_task接受的參數需要是一個協程,但是asyncio.ensure_future除了接受協程,還可以是Future對象或者awaitable對象:

如果參數是協程,其實底層還是用的loop.create_task,返回Task對象

如果是Future對象會直接返回

如果是一個awaitable對象會await這個對象的__await__方法,再執行一次ensure_future,最后返回Task或者Future

所以就像ensure_future名字說的,確保這個是一個Future對象:Task是Future 子類,前面說過一般情況下開發者不需要自己創建Future

其實前面說的asyncio.wait和asyncio.gather里面都用了asyncio.ensure_future。對于絕大多數場景要并發執行的是協程,所以直接用asyncio.create_task就足夠了~

以上是Python中asyncio庫-線程并發函數的案例分析的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女