Python里協程實現原理 從生成器到async/await的協程發展史

python協程的實現經歷了三個階段:生成器、基于生成器的協程和async/await。最初,生成器通過yield和.send()實現了基本的協程功能,具備暫停、恢復及雙向通信能力;隨后,@asyncio.coroutine裝飾器配合yield from實現了異步任務調度,但仍存在語法不直觀、需手動管理事件循環等問題;最終,python 3.5引入async/await語法,async def定義協程函數,await替代yield from,語義更清晰,協程標識更明確,同時Event loop也逐步簡化并模塊化,提升了異步編程效率與性能。

在 Python 中,協程(coroutine)的實現并不是一蹴而就的,而是隨著語言的發展逐步演進而來。從最初的生成器(generator)到如今我們熟悉的 async/await 語法,整個過程可以說是 Python 異步編程的一段進化史。

生成器:協程的基礎

Python 的協程最早是基于生成器構建的。生成器由 yield 關鍵字引入,在早期版本中主要用于惰性地生成數據流。

但人們很快發現,yield 不僅可以用來“產出”值,還可以通過 .send() 方法接收外部傳入的值,這使得生成器具備了“雙向通信”的能力。于是,生成器變成了可以暫停、恢復執行的函數,這就是協程的雛形。

舉個簡單的例子:

立即學習Python免費學習筆記(深入)”;

def simple_coroutine():     x = yield     print("Received:", x)  coro = simple_coroutine() next(coro)  # 啟動協程 coro.send(42)  # 輸出 Received: 42

這個例子展示了協程的基本行為:暫停和恢復,并且能接收外部輸入。雖然看起來簡單,但正是這種機制為后來的異步編程打下了基礎。

基于生成器的協程:手動調度時代

當開發者開始用生成器模擬協程時,出現了像 @asyncio.coroutine 這樣的裝飾器,它本質上就是把一個生成器標記為協程。

這時候的協程需要手動調度,比如使用 yield from 來嵌套調用其他協程:

@asyncio.coroutine def sub_coroutine():     print("Start sub")     yield from asyncio.sleep(1)     print("End sub")  @asyncio.coroutine def main():     yield from sub_coroutine()  asyncio.get_event_loop().run_until_complete(main())

這種方式雖然可行,但有幾個問題:

  • 語法不夠直觀,yield from 容易讓人誤解為只是生成器嵌套
  • 需要手動管理事件循環和調度邏輯
  • 協程和普通生成器沒有明顯區分,容易出錯

async/await:現代協程的誕生

為了改進這些問題,Python 3.5 引入了 async/await 語法,標志著現代協程的正式登場。

  • async def 定義協程函數
  • await 用于等待另一個協程完成,代替了之前的 yield from

上面的例子改寫成 async/await 版本如下:

async def sub_coroutine():     print("Start sub")     await asyncio.sleep(1)     print("End sub")  async def main():     await sub_coroutine()  asyncio.run(main())

這樣寫的好處很明顯:

  • 語義清晰,await 明確表示等待一個協程
  • 協程函數有明確標識(async def),避免與普通函數混淆
  • 更加符合異步編程的思維習慣,也更容易被工具識別和優化

小細節:event loop 的變化也很關鍵

在 async/await 初期,還需要手動獲取和運行 event loop,比如:

loop = asyncio.get_event_loop() loop.run_until_complete(main())

但從 Python 3.7 開始,可以直接使用 asyncio.run(main()),內部自動創建并關閉 event loop,簡化了使用流程。

另外,event loop 的實現也逐漸模塊化,允許第三方庫自定義(如 uvloop),這也讓 Python 的異步性能有了很大提升空間。

總結一下發展脈絡

  • 生成器階段:利用 yield 和 .send() 實現基本的協程功能
  • 生成器協程階段:通過 @asyncio.coroutine 和 yield from 構建異步任務
  • async/await 階段:語法層面支持協程,更清晰、安全、高效

基本上就這些內容了。理解這段歷史,不僅能幫助你更好地寫出高質量的異步代碼,也能讓你明白為什么現在推薦用 async/await 而不是老式的生成器方式。

以上就是Python里協程實現原理 從生成器到async/aw

? 版權聲明
THE END
喜歡就支持一下吧
點贊9 分享