Python里async await語法 異步編程async/await在Python中的實現原理

async/await本質上通過協程和事件循環實現異步編程,提升i/o密集型任務效率。1. async def定義協程函數,調用時返回協程對象而非立即執行;2. await用于等待另一個可等待對象(如協程、任務)完成,在此期間當前協程掛起,控制權交還事件循環;3. 事件循環負責調度所有協程與任務,通過asyncio.run啟動程序并管理其生命周期;4. 并發運行多個協程可通過asyncio.gather()或create_task()將協程包裝為任務并發執行;5. 底層基于生成器與狀態機機制維護協程執行狀態;6. 使用時需注意:不能混用同步異步代碼,避免阻塞操作(如time.sleep),依賴支持異步的第三方庫。

python中使用async/await語法進行異步編程,其實本質上是通過協程(coroutine)機制來實現的。它并不是真正意義上的“并發”執行多個任務,而是通過事件循環(Event loop)調度協程,在合適的時機切換執行流,從而達到高效處理I/O密集型任務的目的。


async/await 是怎么工作的?

當你在函數前加上 async def,Python就會把這個函數變成一個協程函數。調用這個函數并不會立即執行它,而是返回一個協程對象(coroutine Object)。要真正運行這個協程,你需要把它交給事件循環去調度執行。

而 await 的作用就是在這個協程內部等待另一個協程的結果。當遇到 await 時,當前協程會暫停執行,并把控制權交還給事件循環,讓其他協程有機會運行。

舉個簡單的例子:

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

async def say_hello():     print("Hello")     await asyncio.sleep(1)     print("World")  asyncio.run(say_hello())

這段代碼中,say_hello() 是一個協程函數。當它執行到 await asyncio.sleep(1) 時,當前協程會被掛起,事件循環可以去做別的事情(比如運行其他協程),等1秒后時間到了再回來繼續執行。


事件循環:異步程序的核心

所有基于 async/await 的異步操作都依賴于一個核心組件——事件循環(Event Loop)。你可以把它理解為一個調度器,負責管理所有的協程、任務和回調。

Python中的標準庫 asyncio 提供了事件循環的實現。從 Python 3.7 開始,推薦使用 asyncio.run() 來啟動一個異步程序,它會自動創建并關閉事件循環。

如果你需要同時運行多個協程,可以用 asyncio.gather() 或者 asyncio.create_task() 把它們包裝成任務(Task),然后一起交給事件循環:

  • 使用 asyncio.gather():

    async def main():     await asyncio.gather(say_hello(), say_hello())  asyncio.run(main())
  • 使用 create_task():

    async def main():     task1 = asyncio.create_task(say_hello())     task2 = asyncio.create_task(say_hello())     await task1     await task2  asyncio.run(main())

這兩個方法都能讓你的協程并發運行(注意不是并行),適合用來處理網絡請求、文件讀寫這類耗時但不占用CPU的操作。


底層原理:生成器與狀態機的結合

雖然我們看到的是簡潔的 async/await 語法,但其實在底層,Python是用生成器(generator)和狀態機的方式來實現協程的。

  • async def 函數最終會被編譯成一個返回協程對象的函數。
  • 協程對象內部維護了自己的執行狀態,每次被調度時都會從上次暫停的地方繼續執行。
  • 每次遇到 await,Python都會檢查后面的對象是否是一個“可等待對象”(awaitable),比如另一個協程、任務或者Future。
  • 如果是,當前協程就掛起自己,把控制權交給事件循環,直到被再次喚醒。

這背后其實是基于一種叫 promise/Future 的模型,配合事件循環實現了非阻塞的協作式多任務。


實際使用中要注意的問題

  1. 不能隨便混用同步和異步代碼
    如果你在普通函數里直接調用協程函數,它不會執行,只會返回一個協程對象。一定要通過事件循環或 await 去驅動它運行。

  2. 阻塞操作會影響性能
    異步的優勢在于利用空閑時間做其他事。如果你在協程中用了像 time.sleep() 這樣的阻塞操作,整個事件循環都會被卡住。應該用 await asyncio.sleep() 替代。

  3. 第三方庫支持很重要
    要想充分發揮異步能力,你使用的庫也要支持異步方式,比如 aiohttp 替代 requests,asyncpg 替代 psycopg2 等。

基本上就這些。掌握好這些概念之后,你會發現 async/await 并不神秘,只是換了一種方式去組織你的邏輯,讓程序更高效地處理那些等待外部資源的任務。

以上就是Python里async aw

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