python協程進階

概述

很多時候我們使用python的異步,其實並不關心他的發展和演化,只想知道原理和怎麼使用的。

原理

其實協程就是基於cpu寄存器級的上下文切換,而線程是基於內存級切換。協程的切換速度和效率遠高於線程,所以爲python的大併發提供了基礎。

像線程一樣使用協程

任務

線程裏面有主線程和子線程的概念,在協程裏面對應爲主任務和子任務。
同樣的,如果主任務結束,子任務也會自動結束,在線程裏面可以等待子線程完成,同樣的,在協程也可以。

import asyncio

async def coro():
    print("start")
    await asyncio.sleep(1)
    print("wait cancel")
    await asyncio.sleep(5)
    print("cancel fail")

async def t():
    task = asyncio.create_task(coro(),name="coro111")#創建一個協程任務,與主任務並行運行
    print("get_task:",task)
    await asyncio.sleep(3)
    # task.cancel()
    x=asyncio.all_tasks()
    for k in x:
        if k.get_name()=="coro111":
            if not k.cancelled():
                k.cancel()
    # for k in x:
    #     if k.get_name()=="coro111":
    #         if k.cancelled():
    #             k.r
    await asyncio.sleep(5)
    x = asyncio.all_tasks()
    for k in x:
        print(k.get_name())
    print(x)
if __name__ == '__main__':
    loop=asyncio.get_event_loop()
    loop.create_task(t())#創建一個協程任務
    loop.run_forever()#所有任務都執行
    # asyncio.run(t())#等待主任務執行完畢

asyncio.create_task會得到一個任務Task,其對應的主要有如下方法:

Task 對象
class asyncio.Task(coro, *, loop=None, name=None)#一個與 Future 類似 的對象,可運行 Python 協程。非線程安全。Task 對象被用來在事件循環中運行協程。如果一個協程在等待一個 Future 對象,Task 對象會掛起該協程的執行並等待該 Future 對象完成。當該 Future 對象 完成,被打包的協程將恢復執行。
#使用高層級的 asyncio.create_task() 函數來創建 Task 對象
cancelled() #可被用來檢測 Task 對象是否被取消。如果打包的協程沒有抑制 CancelledError 異常並且確實被取消,該方法將返回 True。
#Task 對象支持 contextvars 模塊。當一個 Task 對象被創建,它將複製當前上下文,然後在複製的上下文中運行其協程。
cancel()#請求取消 Task 對象。這將安排在下一輪事件循環中拋出一個 CancelledError 異常給被封包的協程。

cancelled()#如果 Task 對象 被取消 則返回 True。

done()#如果 Task 對象 已完成 則返回 True。當 Task 所封包的協程返回一個值、引發一個異常或 Task 本身被取消時,則會被認爲 已完成。

result()#返回 Task 的結果。

#如果 Task 對象 已完成,其封包的協程的結果會被返回 (或者當協程引發異常時,該異常會被重新引發。)
#如果 Task 對象 被取消,此方法會引發一個 CancelledError 異常。
#如果 Task 對象的結果還不可用,此方法會引發一個 InvalidStateError 異常。

exception()#返回 Task 對象的異常。

add_done_callback(callback, *, context=None)#添加一個回調,將在 Task 對象 完成 時被運行。

remove_done_callback(callback)#從回調列表中移除 callback 。

get_stack(*, limit=None)#返回此 Task 對象的棧框架列表。

print_stack(*, limit=None, file=None)#打印此 Task 對象的棧或回溯。

get_coro()
返回由 Task 包裝的協程對象。

get_name()#返回 Task 的名稱。
set_name(value)#設置 Task 的名稱。value 參數可以爲任意對象,它隨後會被轉換爲字符串。在默認的 Task 實現中,名稱將在任務對象的 repr() 輸出中可見。

示例:

async def cancel_me():
    print('cancel_me(): before sleep')

    try:
        # Wait for 1 hour
        await asyncio.sleep(3600)
    except asyncio.CancelledError:
        print('cancel_me(): cancel sleep')
        raise
    finally:
        print('cancel_me(): after sleep')

async def main():
    # Create a "cancel_me" Task
    task = asyncio.create_task(cancel_me())

    # Wait for 1 second
    await asyncio.sleep(1)

    task.cancel()
    try:
        await task
    except asyncio.CancelledError:
        print("main(): cancel_me is cancelled now")

asyncio.run(main())
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章