[Python教學] 進階:非同步程式設計

[Python教學] 進階:非同步程式設計

更新於 發佈於 閱讀時間約 6 分鐘

在這篇文章中,我們將深入探討 Python 中的非同步程式設計,特別是使用 asyncio 模組來實現事件循環和協程。這將幫助你理解如何在 I/O 密集型任務中提高效率,並充分利用 Python 的非同步特性。

什麼是非同步程式設計?

非同步程式設計允許程式在等待某些操作(如網路請求或檔案讀寫)完成時,能夠執行其他任務。這種方式特別適合 I/O 密集型的應用,例如網頁爬蟲或伺服器應用。與傳統的同步程式設計相比,非同步程式設計可以顯著提高應用的響應速度和效能。

asyncio 模組介紹

asyncio 是 Python 標準庫的一部分,自 Python 3.4 開始提供支持。它提供了一個事件循環來管理協程的執行,並使用 async 和 await 語法來簡化非同步程式碼的編寫。

事件循環 (Event Loop)

事件循環是 asyncio 的核心,它負責調度和執行協程。當一個協程遇到 await 語句時,它會暫停執行,並將控制權返回給事件循環,這樣其他協程就可以運行。

協程 (Coroutine)

協程是使用 async def 定義的函數,可以被暫停和恢復。協程內部可以使用 await 來等待其他協程或異步操作的完成。

使用 asyncio 的基本範例

下面是一個簡單的範例,展示了如何使用 asyncio 進行非同步程式設計:

import asyncio

# 定義一個協程
async def say_hello():
print("Hello")
await asyncio.sleep(1) # 模擬一個耗時的 I/O 操作
print("World")

# 執行事件循環
async def main():
await say_hello()

# 使用 asyncio.run() 啟動事件循環
if __name__ == "__main__":
asyncio.run(main())

在這個範例中,我們定義了一個名為 say_hello 的協程,它會顯示 "Hello",然後暫停一秒鐘,再顯示 "World"。我們使用 asyncio.run() 啟動事件循環並執行主協程。

事件循環的操作

創建和運行事件循環

除了使用 asyncio.run(),我們還可以手動創建和運行事件循環:

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

這段程式碼首先獲取當前的事件循環,然後運行主協程,最後關閉事件循環。

任務 (Task) 和 Future

在 asyncio 中,任務是對協程的封裝,可以通過 asyncio.create_task() 或 asyncio.ensure_future() 來創建。任務會被調度到事件循環中執行,而 Future 對象則表示一個尚未完成的操作。

task = asyncio.create_task(say_hello())
await task # 等待任務完成

同時運行多個協程

我們可以使用 asyncio.gather() 同時運行多個協程:

async def say_goodbye():
print("Goodbye")
await asyncio.sleep(1)
print("See you later")

async def main():
await asyncio.gather(say_hello(), say_goodbye())

if __name__ == "__main__":
asyncio.run(main())

在這裡,我們定義了另一個協程 say_goodbye(),並使用 asyncio.gather() 同時調用兩個協程。這樣可以更有效地利用等待時間。

錯誤處理

在非同步程式設計中,錯誤處理也很重要。我們可以使用 try-except 來捕獲異常:

async def risky_operation():
raise ValueError("An error occurred!")

async def main():
try:
await risky_operation()
except ValueError as e:
print(f"Caught an error: {e}")

if __name__ == "__main__":
asyncio.run(main())

總結

透過本文,你應該能夠理解如何使用 Python 的 asyncio 模組進行非同步程式設計。掌握事件循環、協程及其運作方式,可以幫助你有效地處理 I/O 密集型任務,提高應用程序的性能。在實際開發中,你可以根據需要選擇合適的方法來實現非同步處理,以達到最佳效果。

avatar-img
追極光的北極熊|軟體工程師的小天地
6會員
116內容數
歡迎來到我的部落格!這裡記錄了軟體工程師的日常生活點滴,並分享程式設計與演算法的實用教學。無論你是初學者還是有經驗的開發者,都能在這裡找到深入淺出的技術解析與實戰技巧。此外,我也會分享工作中的心路歷程與學習心得,讓你不僅學到技術,更能瞭解軟體開發的實際應用與挑戰。希望透過這個平台,能與你共同成長,激發對技術的熱情!
留言
avatar-img
留言分享你的想法!
當我們開發程式時,功能能正常運作固然重要,但在資料量變大或執行時間變長時,效能就成為不可忽視的一環。尤其在 Web 應用、資料分析或科學運算中,程式跑得快與否,直接影響使用者體驗與系統成本。
嘿,大家好!上篇教學文章我們做出了一個待辦事項清單,已經有點小工具的感覺了吧?今天我們要再升級,來做個「簡單記事本」。這個專案不只可以寫東西,還能存檔、讀檔,甚至換字體大小,感覺就像自己寫了個迷你軟體!
嘿,大家好!走到這一步,我們已經玩過 Tkinter 的基本招式、佈局、事件處理,還搞了些進階元件,應該有點信心了吧?今天我們要把這些功夫練成一套連招,來做個實用的「待辦事項清單」(To-Do List),順便聊聊怎麼把程式寫得更漂亮、更好用。準備好了嗎?這就上場啦!
當我們開發程式時,功能能正常運作固然重要,但在資料量變大或執行時間變長時,效能就成為不可忽視的一環。尤其在 Web 應用、資料分析或科學運算中,程式跑得快與否,直接影響使用者體驗與系統成本。
嘿,大家好!上篇教學文章我們做出了一個待辦事項清單,已經有點小工具的感覺了吧?今天我們要再升級,來做個「簡單記事本」。這個專案不只可以寫東西,還能存檔、讀檔,甚至換字體大小,感覺就像自己寫了個迷你軟體!
嘿,大家好!走到這一步,我們已經玩過 Tkinter 的基本招式、佈局、事件處理,還搞了些進階元件,應該有點信心了吧?今天我們要把這些功夫練成一套連招,來做個實用的「待辦事項清單」(To-Do List),順便聊聊怎麼把程式寫得更漂亮、更好用。準備好了嗎?這就上場啦!