大多數的python web server 都有使用到到 async def 與 await,因為對這兩個關鍵字沒很熟,所以就藉機紀錄一下,避免之後忘記。
我用到的 web server source code:
https://github.com/tornadoweb/tornado/blob/master/tornado/web.py
傳統的, 循序的程式寫法, 遇到 sleep 會真的讓cpu idle 2秒, 這樣對multi thread 程式沒效率, 以下面的範來來說, 5個 function 都 wait 2秒, 需要花10秒跑完, 但如果使用 aync def + await 就可以5個 function 一起跑, 在2秒之後, 大家一起跑完.
循序+同步的寫法:
import time
def dosomething(i):
print(f"第 {i} 次開始")
time.sleep(2)
print(f"第 {i} 次結束")
if __name__ == "__main__":
start = time.time()
for i in range(5):
dosomething(i+1)
print(f"time: {time.time() - start} (s)")
結果
第 1 次開始
第 1 次結束
第 2 次開始
第 2 次結束
第 3 次開始
第 3 次結束
第 4 次開始
第 4 次結束
第 5 次開始
第 5 次結束
time: 10.048049688339233 (s)
非同步寫法:
import time
import asyncio
async def dosomething(i):
print(f"第 {i} 次開始")
await asyncio.sleep(2)
print(f"第 {i} 次結束")
if __name__ == "__main__":
start = time.time()
tasks = [dosomething(i+1) for i in range(5)]
asyncio.run(asyncio.wait(tasks))
print(f"time: {time.time() - start} (s)")
執行結果:
第 2 次開始
第 1 次開始
第 3 次開始
第 4 次開始
第 5 次開始
第 2 次結束
第 3 次結束
第 5 次結束
第 1 次結束
第 4 次結束
time: 2.011152982711792 (s)
與 async def + await 類似的是 Coroutine,
Coroutine 的解釋:
Coroutines are a more generalized form of subroutines. Subroutines are entered at one point and exited at another point. Coroutines can be entered, exited, and resumed at many different points. They can be implemented with the async def statement. See also PEP 492 .GLOSSARY — PYTHON 3.8.2 DOCUMENTATION
所謂 Coroutine 就是一個可以暫停將執行權讓給其他 Coroutine 或 Awaitables obj 的函數,等其執行完後再繼續執行,並可以多次的進行這樣的暫停與繼續。
▍使用須知:
- Python 3.5+ 開始可以使用 asyncio 標準庫和 await syntax 語法糖來寫 Coroutines:
PEP 492 — Coroutines with async and await syntax | Python.org - Python 3.7+ 開始可以使用 asyncio.run( ):
cpython/runners.py at 3.8 · python/cpython · GitHub
所以, 有空把執行環境, 升到 3.5+ 或 3.7+ 會好一點.
相關文章
【Python教學】淺談 Coroutine 協程使用方法
https://www.maxlist.xyz/2020/03/29/python-coroutine/
[Python] async def & await 重點整理
https://ithelp.ithome.com.tw/articles/10262385