中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

Python中asyncio怎么用

發布時間:2021-08-25 11:19:41 來源:億速云 閱讀:166 作者:小新 欄目:開發技術

小編給大家分享一下Python中asyncio怎么用,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

asyncio介紹

熟悉c#的同學可能知道,在c#中可以很方便的使用 async 和 await 來實現異步編程,那么在python中應該怎么做呢,其實python也支持異步編程,一般使用 asyncio 這個庫,下面介紹下什么是 asyncio :

asyncio 是用來編寫 并發 代碼的庫,使用 async/await 語法。 asyncio 被用作多個提供高性能 Python 異步框架的基礎,包括網絡和網站服務,數據庫連接庫,分布式任務隊列等等。 asyncio 往往是構建 IO 密集型和高層級 結構化 網絡代碼的最佳選擇。

asyncio中的基本概念

可以看見,使用asyncio庫我們也可以在python代碼中使用 async 和 await 。在 asyncio 中,有四個基本概念,分別是:

Eventloop

Eventloop 可以說是 asyncio 應用的核心,中央總控, Eventloop 實例提供了注冊、取消、執行任務和回調 的方法。 簡單來說,就是我們可以把一些異步函數注冊到這個事件循環上,事件循環回循環執行這些函數(每次只能執行一個),如果當前正在執行的函數在等待I/O返回,那么事件循環就會暫停它的執行去執行其他函數。當某個函數完成I/O后會恢復,等到下次循環到它的時候就會繼續執行。

Coroutine

協程本質就是一個函數,

import asyncio
import time
async def a():
 print('Suspending a')
 await asyncio.sleep(3)
 print('Resuming a')
async def b():
 print('Suspending b')
 await asyncio.sleep(1)
 print('Resuming b')
async def main():
 start = time.perf_counter()
 await asyncio.gather(a(), b())
 print(f'{main.__name__} Cost: {time.perf_counter() - start}')
if __name__ == '__main__':
 asyncio.run(main())

執行上述代碼,可以看到類似這樣的輸出:

Suspending a
Suspending b
Resuming b
Resuming a
main Cost: 3.0023356619999997

關于協程的具體介紹,可以參考我以前的文章python中的協程 不過以前的那種寫法,需要使用裝飾器,已經過時了。

Future

Future 是表示一個“未來”對象,類似于 javascript 中的 promise ,當異步操作結束后會把最終結果設置到這個 Future 對象上, Future 是對協程的封裝。

>>> import asyncio
>>> def fun():
...  print("inner fun")
...  return 111
... 
>>> loop = asyncio.get_event_loop()
>>> future = loop.run_in_executor(None, fun) #這里沒有使用await
inner fun
>>> future #可以看到,fun方法狀態是pending
<Future pending cb=[_chain_future.<locals>._call_check_cancel() at /usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/futures.py:348]>
>>> future.done() # 還沒有完成
False
>>> [m for m in dir(future) if not m.startswith('_')]
['add_done_callback', 'cancel', 'cancelled', 'done', 'exception', 'get_loop', 'remove_done_callback', 'result', 'set_exception', 'set_result']
>>> future.result() #這個時候如果直接調用result()方法會報錯
Traceback (most recent call last):
 File "<input>", line 1, in <module>
asyncio.base_futures.InvalidStateError: Result is not set.
>>> async def runfun():
...  result=await future
...  print(result)
...  
>>>loop.run_until_complete(runfun()) #也可以通過 loop.run_until_complete(future) 來執行,這里只是為了演示await
111
>>> future
<Future finished result=111>
>>> future.done()
True
>>> future.result()
111
Task

Eventloop 除了支持協程,還支持注冊 Future 和 Task 2種類型的對象,而 Future 是協程的封裝, Future 對象提供了很多任務方法(如完成后的回調,取消,設置任務結果等等),但是一般情況下開發者不需要操作 Future 這種底層對象,而是直接用 Future 的子類 Task 協同的調度協程來實現并發。那么什么是 Task 呢?下面介紹下:

一個與 Future 類似的對象,可運行 Python 協程。非線程安全。 Task 對象被用來在事件循環中運行協程。如果一個協程在等待一個 Future 對象, Task 對象會掛起該協程的執行并等待該 Future 對象完成。當該 Future 對象完成被打包的協程將恢復執行。 事件循環使用協同日程調度: 一個事件循環每次運行一個 Task 對象。而一個 Task 對象會等待一個 Future 對象完成,該事件循環會運行其他 Task 、回調或執行IO操作。

下面看看用法:

>>> async def a():
...  print('Suspending a')
...  await asyncio.sleep(3)
...  print('Resuming a')
...  
>>> task = asyncio.ensure_future(a())
>>> loop.run_until_complete(task)
Suspending a
Resuming a

asyncio中一些常見用法的區別

Asyncio.gather和asyncio.wait

我們在上面的代碼中用到過 asyncio.gather ,其實還有另外一種用法是 asyncio.wait ,他們都可以讓多個協程并發執行,那么他們有什么區別呢?下面介紹下。

>>> import asyncio
>>> 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'
... 
>>> async def fun1():
...  return_value_a, return_value_b = await asyncio.gather(a(), b())
...  print(return_value_a,return_value_b)
...  
>>> asyncio.run(fun1())
Suspending a
Suspending b
Resuming b
Resuming a
A B
>>> async def fun2():
...  done,pending=await asyncio.wait([a(),b()])
...  print(done)
...  print(pending)
...  task=list(done)[0]
...  print(task)
...  print(task.result())
...  
>>> asyncio.run(fun2())
Suspending b
Suspending a
Resuming b
Resuming a
{<Task finished coro=<a() done, defined at <input>:1> result='A'>, <Task finished coro=<b() done, defined at <input>:8> result='B'>}
set()
<Task finished coro=<a() done, defined at <input>:1> result='A'>
A

根據上述代碼,我們可以看出兩者的區別:

asyncio.gather 能收集協程的結果,而且會按照輸入協程的順序保存對應協程的執行結果,而 asyncio.wait 的返回值有兩項,第一項是完成的任務列表,第二項表示等待完成的任務列表。

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

>>> async def fun2():
...  done,pending=await asyncio.wait([a(),b()],return_when=asyncio.tasks.FIRST_COMPLETED)
...  print(done)
...  print(pending)
...  task=list(done)[0]
...  print(task)
...  print(task.result())
...  
>>> asyncio.run(fun2())
Suspending a
Suspending b
Resuming b
{<Task finished coro=<b() done, defined at <input>:8> result='B'>}
{<Task pending coro=<a() running at <input>:3> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x10757bf18>()]>>}
<Task finished coro=<b() done, defined at <input>:8> result='B'>
B

一般情況下,用 asyncio.gather 就足夠了。

asyncio.create_task和loop.create_task以及asyncio.ensure_future

這三種方法都可以創建 Task ,從Python3.7開始可以統一的使用更高階的 asyncio.create_task .其實 asyncio.create_task 就是用的 loop.create_task . loop.create_task 接受的參數需要是一個協程,但是 asyncio.ensure_future 除了接受協程,還可以是 Future 對象或者 awaitable 對象:

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

  2. 如果是 Future 對象會直接返回

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

所以 ensure_future 方法主要就是確保這是一個 Future 對象,一般情況下直接用 asyncio.create_task 就可以了。

注冊回調和執行同步代碼

可以使用 add_done_callback 來添加成功回調:

def callback(future):
 print(f'Result: {future.result()}')
def callback2(future, n):
 print(f'Result: {future.result()}, N: {n}')
async def funa():
 await asyncio.sleep(1)
 return "funa"
async def main():
 task = asyncio.create_task(funa())
 task.add_done_callback(callback)
 await task
 #這樣可以為callback傳遞參數
 task = asyncio.create_task(funa())
 task.add_done_callback(functools.partial(callback2, n=1))
 await task
if __name__ == '__main__':
 asyncio.run(main())

執行同步代碼

如果有同步邏輯,想要用 asyncio 來實現并發,那么需要怎么做呢?下面看看:

def a1():
 time.sleep(1)
 return "A"
async def b1():
 await asyncio.sleep(1)
 return "B"
async def main():
 loop = asyncio.get_running_loop()
 await asyncio.gather(loop.run_in_executor(None, a1), b1())
if __name__ == '__main__':
 start = time.perf_counter()
 asyncio.run(main())
 print(f'main method Cost: {time.perf_counter() - start}')
# 輸出: main method Cost: 1.0050589740000002

可以使用 run_into_executor 來將同步函數邏輯轉化成一個協程,第一個參數是要傳遞 concurrent.futures.Executor 實例的,傳遞 None 會選擇默認的 executor 。

以上是“Python中asyncio怎么用”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

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

AI

邢台县| 东明县| 本溪| 蒲城县| 洪泽县| 巴林右旗| 绵竹市| 日照市| 西充县| 兴仁县| 白城市| 孝昌县| 三门峡市| 分宜县| 长治市| 孟津县| 岚皋县| 长兴县| 井研县| 格尔木市| 连江县| 日喀则市| 大石桥市| 梓潼县| 昆明市| 布拖县| 邢台市| 葫芦岛市| 瓦房店市| 苏尼特左旗| 辰溪县| 梅州市| 漳州市| 吉林省| 祁连县| 北碚区| 黄山市| 宁晋县| 安远县| 宁武县| 师宗县|