亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Python中的asyncio代碼詳解

系統(tǒng) 1827 0

asyncio介紹

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

asyncio 是用來編寫 并發(fā) 代碼的庫,使用?async/await 語法。?asyncio 被用作多個提供高性能?Python 異步框架的基礎(chǔ),包括網(wǎng)絡(luò)和網(wǎng)站服務(wù),數(shù)據(jù)庫連接庫,分布式任務(wù)隊列等等。?asyncio 往往是構(gòu)建 IO 密集型和高層級 結(jié)構(gòu)化 網(wǎng)絡(luò)代碼的最佳選擇。

asyncio中的基本概念

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

Eventloop

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

Coroutine

協(xié)程本質(zhì)就是一個函數(shù),

            
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())
          

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

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

關(guān)于協(xié)程的具體介紹,可以參考我以前的文章python中的協(xié)程 不過以前的那種寫法,需要使用裝飾器,已經(jīng)過時了。

Future

Future 是表示一個“未來”對象,類似于?javascript 中的?promise ,當(dāng)異步操作結(jié)束后會把最終結(jié)果設(shè)置到這個?Future 對象上,?Future 是對協(xié)程的封裝。

            
>>> 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方法狀態(tài)是pending

            
              ._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() #這個時候如果直接調(diào)用result()方法會報錯
Traceback (most recent call last):
 File "
              
              ", line 1, in 
              
                
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) 來執(zhí)行,這里只是為了演示await
111
>>> future

                
                  
>>> future.done()
True
>>> future.result()
111
Task
                
              
            
          

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

一個與?Future 類似的對象,可運(yùn)行?Python 協(xié)程。非線程安全。?Task 對象被用來在事件循環(huán)中運(yùn)行協(xié)程。如果一個協(xié)程在等待一個?Future 對象,?Task 對象會掛起該協(xié)程的執(zhí)行并等待該?Future 對象完成。當(dāng)該?Future 對象完成被打包的協(xié)程將恢復(fù)執(zhí)行。 事件循環(huán)使用協(xié)同日程調(diào)度: 一個事件循環(huán)每次運(yùn)行一個?Task 對象。而一個?Task 對象會等待一個?Future 對象完成,該事件循環(huán)會運(yùn)行其他?Task 、回調(diào)或執(zhí)行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中一些常見用法的區(qū)別

Asyncio.gather和asyncio.wait

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

            
>>> 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
{
            
              
              :1> result='A'>, 
              
                
                :8> result='B'>}
set()

                
                  
                  :1> result='A'>
A
                
              
            
          

根據(jù)上述代碼,我們可以看出兩者的區(qū)別:

asyncio.gather 能收集協(xié)程的結(jié)果,而且會按照輸入?yún)f(xié)程的順序保存對應(yīng)協(xié)程的執(zhí)行結(jié)果,而?asyncio.wait 的返回值有兩項,第一項是完成的任務(wù)列表,第二項表示等待完成的任務(wù)列表。

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

            
>>> 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
{
            
              
              :8> result='B'>}
{
              
                
                :3> wait_for=
                
                  ()]>>}

                  
                    
                    :8> result='B'>
B
                  
                
              
            
          

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

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

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

  1. 如果參數(shù)是協(xié)程,其底層使用?loop.create_task ,返回?Task 對象
  2. 如果是?Future 對象會直接返回
  3. 如果是一個?awaitable 對象,會?await 這個對象的?__await__ 方法,再執(zhí)行一次?ensure_future ,最后返回?Task 或者?Future 。

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

注冊回調(diào)和執(zhí)行同步代碼

可以使用?add_done_callback 來添加成功回調(diào):

            
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傳遞參數(shù)
 task = asyncio.create_task(funa())
 task.add_done_callback(functools.partial(callback2, n=1))
 await task
if __name__ == '__main__':
 asyncio.run(main())
          

執(zhí)行同步代碼

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

            
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 來將同步函數(shù)邏輯轉(zhuǎn)化成一個協(xié)程,第一個參數(shù)是要傳遞?concurrent.futures.Executor 實例的,傳遞?None 會選擇默認(rèn)的?executor 。

總結(jié)

以上所述是小編給大家介紹的Python中的asyncio代碼詳解,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。。?/p>

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 亚洲欧美自拍另类图片色 | 久久r这里只有精品 | 国产成人毛片精品不卡在线 | 色的综合| 狠狠操狠狠插 | 波多野结中文字幕在线69视频 | 亚洲色五月 | 久久国产精品99久久久久久牛牛 | 成人网18免费网 | 日韩欧美在线一级一中文字暮 | 欧美日韩亚洲精品一区二区 | 国产精品自在自线免费观看 | 久久久这里有精品 | 91亚洲免费视频 | 亚洲女bbwxxxx另类 | 日本不卡免费新一区二区三区 | 奇米影视777在线播放 | 国产永久免费爽视频在线 | 国产美女一级高清免费观看 | 亚洲精品综合一区在线 | 成人精品亚洲人成在线 | 天天拍夜夜添久久精品免费 | 免费区欧美一级毛片精品 | 亚洲国产精品67194成人 | 久久精品国产亚洲a | 久久精品欧美一区二区 | 久久国产精品自由自在 | 在线观看亚洲视频 | 69成人做爰视频在线观看 | www.亚洲一区二区三区 | 欧美一级看片a免费观看 | 精品久久久日韩精品成人 | 久艾草国产成人综合在线视频 | 麻豆成人久久精品二区三区小说 | 九九热在线视频观看 | 国产成人亚洲综合91精品555 | 四虎影视精品永久免费 | 欧美一级www片免费观看 | 欧洲成人在线 | 久久夜色精品国产噜噜小说 | 亚洲综合色dddd26 |