Python 異步協程 async/await/asyncio


引自:https://blog.csdn.net/sunt2018/article/details/105138121

異步IO asyncio協程

asyncio 是python3.4 引入的,內置的對異步IO的支持。

asyncio編程是一個消息循環,我們從asyncio中獲取一個EventLoop引用

然后把協程放到EventLoop中執行,就實現了異步IO

 

協程常見名字

先了解以下名詞,有助於理解程序編寫

  • event_loop 事件循環: 程序開啟一個循環,我們把函數注冊到loop里,滿足條件就會執行

  • coroutine 協程: async def 定義的函數,它不能直接執行,返回的是協程對象,它要注冊到loop中,由loop去執行調用

  • task 任務: 一個協程對象就是一個原生可以掛起的函數,任務則是對協程對象進一步封裝,增加了任務的各種狀態,(比如未執行,執行中,執行結束,返回結果等等?。)

    task 是 future的子類

  • future : 代表將來執行或沒有執行的任務的結果,它個task沒有本質區別

  • async/await : python3.5 用於定義協程的關鍵字

 

創建一個協程 Coroutine

import asyncio,time

# 記錄開始時間
now = lambda: time.time()
start = now()

# 01.定義一個協程
async def do_work(num):
    print("num:",num)

coroutine = do_work(1)

# 02.創建事件循環
loop = asyncio.get_event_loop()

# 03.將協程對象放入事件循環中
loop.run_until_complete(coroutine)

# 記錄結束時間
print(now() - start)

  

創建一個任務 Task

loop.run_until_complete方法傳入協程,自動將協程裝成任務task,它也可以直接接收task

創建task 使用以下方法都可以

asyncio.ensure_future(coroutine)

loop.create_task(coroutine)

task是future的子類。

isinstance(task,asyncio.Future) 返回Ture

import asyncio,time

# 記錄開始時間
now = lambda: time.time()
start = now()

# 01.定義一個協程
async def do_work(num):
    print("num:",num)

coroutine = do_work(1)

# 02.創建事件循環
loop = asyncio.get_event_loop()

# 03.創建任務Task
task = asyncio.ensure_future(coroutine)
# 或者下面的方式 創建task也可以
# task = loop.create_task(coroutine)

# 04.將任務注冊到事件循環中
loop.run_until_complete(task)

# 記錄結束時間
print(now() - start)

  

獲取返回結果 回調函數future/直接使用Task獲取

import asyncio,time

# 記錄開始時間
now = lambda: time.time()
start = now()

# 01.定義一個協程
async def do_work(num):
    print("num:",num)
    return "num is {}".format(num)

coroutine = do_work(3)


# 02.定義回調函數
def callback(future):
    print('result is',future.result())

# 03.創建事件循環
loop = asyncio.get_event_loop()

# 04.創建任務Task
task = loop.create_task(coroutine)

# 05.給task任務綁定回調函數
task.add_done_callback(callback)

# 06.將任務注冊到事件循環中
loop.run_until_complete(task)

# 記錄結束時間
print(now() - start)

  

不綁定回調,直接使用Task的結果

task.result(),必須任務執行完畢后才有這個,不然會報錯

阻塞 await

import asyncio,time

# 記錄開始時間
now = lambda: time.time()
start = now()

# 01.定義一個協程
async def do_work(num):
    print("num:",num)
    await asyncio.sleep(num)
    return "sleep is {}".format(num)

coroutine = do_work(3)


# 02.創建事件循環
loop = asyncio.get_event_loop()

# 03.創建任務Task
task = loop.create_task(coroutine)
print(task.result())

# 04.將任務注冊到事件循環中
loop.run_until_complete(task)

# 記錄結束時間
print(now() - start)
print(task.result())

  

asyncio 實現並發

import asyncio,time

# 記錄開始時間
now = lambda: time.time()
start = now()

# 01.定義一個協程
async def do_work(num):
    print("num:",num)
    await asyncio.sleep(num)
    return "sleep is {}".format(num)

coroutine1 = do_work(1)
coroutine2 = do_work(2)
coroutine3 = do_work(3)



# 02.創建任務Task
tasks =[
    asyncio.ensure_future(coroutine1),
    asyncio.ensure_future(coroutine2),
    asyncio.ensure_future(coroutine3),
    
]

# 02.創建事件循環
loop = asyncio.get_event_loop()

# 04.將任務注冊到事件循環中
loop.run_until_complete(asyncio.wait(tasks))

# 記錄結束時間
print(now() - start)
for task in tasks:
    print(task.result())

  

協程嵌套

import time
import asyncio


async def do_work(x):
    print("do...work.....")
    await asyncio.sleep(x)
    return 'Done result'


async def main():
    # 創建多個協程對象
    coroutine1 = do_work(1)
    coroutine2 = do_work(2)
    coroutine3 = do_work(4)
    
    tasks = [
        asyncio.ensure_future(coroutine1),
        asyncio.ensure_future(coroutine2),
        asyncio.ensure_future(coroutine3)
    ]
    
    # --------------------------------------------
    # 獲取返回結果的方式 1
    dones,pendings = await asyncio.wait(tasks)
    # dones 是任務
    for task in dones:
        print(task.result())
    # --------------------------------------------
    
# 將協程main 放入到 loop中
loop = asyncio.get_event_loop()
loop.run_until_complete(main())

  

 獲取返回結果的方式2
results =  await asyncio.gather(*tasks)
for result in results():
    print(result)

  

# 獲取方式3,不在main中獲取,而是在外面獲取
async def main:
    # .....
    return await asyncio.gather(*tasks)

results = loop.run_until_complete(main())
for result in results():
    print(result)

  

# 獲取方式4,不在main中獲取,而是在外面獲取
async def main:
    # .....
    return await asyncio.wait(tasks)

dones,pendings = loop.run_until_complete(main())
for task in dones:
    print(task.result())

  

# 獲取方式5,還是在main中

for task in asyncio.as_complete(tasks):
    result = await task
    print(result)

  

協程的停止

future 中的幾種狀態

  • Pending 創建future的時候,task為 pending
  • Running 事件循環執行的時候,task是running
  • Done 執行完畢 task狀態是done
  • Cancelled 任務取消
  • import time
    import asyncio
    
    
    async def do_work(x):
        print("do...work.....")
        await asyncio.sleep(x)
        return 'Done result'
    
    
    coroutine1 = do_work(1)
    coroutine2 = do_work(2)
    coroutine3 = do_work(4)
    
    
    tasks = [
            asyncio.ensure_future(coroutine1),
            asyncio.ensure_future(coroutine2),
            asyncio.ensure_future(coroutine3),
    ]
    
    
    start = time.time()
    loop = asyncio.get_event_loop()
    
    try:
        loop.run_until_complete(asyncio.wait(tasks))
    except KeyboardInterrupt as e:
        for task in asyncio.Task.all_tasks():
            print(task.cancel())
        loop.stop()
        loop.run_forever()
    finally:
        loop.close()
    
    print(time.time() - start)
    

      


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM