Python asyncio簡單整理
前言
Python 為了避免產生 blocking 問題,替耗時的 IO、計算或網路相關操作提供了 asyncio,可以用並發的方式完成工作,同時最大限度地提高作業效率。
正文
協程和任務(Coroutines and Tasks)
何謂協程?
協程指的是有宣告為 async 的函式
1 | import asyncio |
此時main()
就是協程,無法直接被執行
何謂任務?
協程可以被裝成任務,接續上面的程式碼
1 | task = asyncio.create_task(main()) |
此時task
會是一個任務,任務比起一般協程能做出更多流程控制。
協程和任務的使用
若要使用協程和任務,可使用await
關鍵字
1 | await task |
在這邊要注意,await task
和await main()
都會回傳main
函式的執行結果,但是task
是在create_task()
沒多久後就執行了(會被丟進事件迴圈等待執行),後者則是執行await main()
時才會被執行。
使用
await
的關鍵字,表示要 Python 等待後方任務或協程執行完畢再繼續執行下去。在等待執行完畢的期間,Python 會不斷切換工作執行,直到等待中的任務完成。
雖然
asyncio.run()
可以用來執行協程和任務,但它其實是用於 async 程式的進入點,因此在正常情況下,一個 async 只能有一個asyncio.run()
,否則會引發錯誤
Queue Lock 與 Event
可以用來控制執行情況
Queue 佇列
先進先出
可以塞入需要處理的物件,在音樂機器人等需要有佇列時很有用
1 | queue = asyncio.Queue() |
Lock 鎖
能調控 IO 資源的取得,上鎖以後不能被使用,直到鎖被釋放為止,通常搭配async with
使用
1 | lock = asyncio.Lock() |
Event 事件
能調控程式是否要繼續向下執行(wait()
),常用於 callback 函數中。 內部有個參數預設是false
,可透過函數控制。當執行wait()
時,若參數是true
就會立刻繼續執行,否則會持續等待。
1 | async def waiter(event): |
對抗耗時的 IO 操作
面對耗時的 IO 操作,可以使用比較低層的操作方法
1 | import asyncio |
用這種方法處理,主線程就不會卡住,在 Discord Bot 上常常用到。
結語
其實這篇是整理幾個重點給我自己看的,文中只有簡單帶過常用的東西,如果需要更深層的知識需要自己去搜尋。
有任何錯誤請通知我。