vocus logo

方格子 vocus

【Python - asyncio】非同步 I/O 簡介

更新 發佈閱讀 6 分鐘
vocus|新世代的創作平台


為什麼需要非同步? 我們在「【Web微知識系列】 Web Workers」有介紹到在瀏覽器可執行腳本Javascript環境底下如何完成非同步的操作, 主要是為了讓任務更有效率的進行, 不會因為一個非常耗時的工作堵塞住整個服務, 導致無法服務他人的窘境。


大家應該經常在餐廳裡會看到服務員協助顧客點餐吧! 而服務員的工作除了送餐、清潔之外還要協助顧客點餐, 那麼當每位顧客都花費10分鐘在思考要點什麼時, 服務員若在原地等待是一個非常浪費資源的行為, 因此通常每位服務員都先將顧客帶到位子上之後, 說明餐點跟給予菜單之後, 便可以釋出資源去服務其他客人, 甚至能夠完成其他工作, 這就是一個在我們生活中常常出現的非同步情境。


而Python在3.4版之後就有 asyncio 模組了, 但相關的API函數尚未完全, 因此使用起來並非那麼直觀, 而在3.8之後的功能就加入了許多語法糖封裝, 讓我們能夠很簡易的使用這些功能完成我們的非同步應用場景。


開發程式的過程中, 相信除了本身程式的運算之外, 更多的是網路的傳輸(外部API)、硬碟的存取(I/O), 而這些外部的服務都不應該阻塞我們的程式, 因此我們可以透過 asyncio 來做一個任務委外的動作, 而程式本身的運算也能夠持續執行, 這就是非同步的魅力所在。


概念建立之後, 我們就可以開始進行簡易的實作囉! 就讓我們一同探索非同步的 asyncio 吧!


協程 (Coroutine)

協程是一個比較特殊的函數, 也是為了解決單執行緒應用之中的等待浪費資源問題, 與常規函數不同,協程可以在適當的時機暫停、恢復和交互執行,這種能力使得協程特別適合處理非同步的任務,比如 I/O 操作、網絡請求等需要等待的工作。


async與await

這兩個語法糖主要是讓我們更直觀的標示異步的函式與執行的進入點。

  • async:用來宣告函數能夠有異步的功能。
  • await:用來標記異步的執行。

# async 宣告一個非同步函式
async def do(...):
...


...
...
# await 將控制權交給事件循環並等待結果回傳
await do(...)


這些語法想必常常在異步的Python程式中隨處所見吧, 這也是整個 asyncio 用來標示非同步函式的主要標誌。


關於事件循環

vocus|新世代的創作平台

回顧「【Web微知識系列】 Web Workers」 我們有提到事件循環的概念, 我們還是以餐廳服務員為例, 當我們收到客人的菜單時, 會將菜單交給內場的夥伴們進行料理, 而服務員就可以趁著備料的時候進行其他工作項目(擦桌子、帶位…), 直到料理完成之後, 切換回來將美味的料理交給客人享用, 這整個餐廳的日常工作就像是一個事件循環一般。


那在 asyncio 的世界裡應該怎麼使用呢? 我們可以透過「asyncio.get_event_loop」來建立一個事件循環, 然後再將上述的 「async func」帶入, 直到事件循環結束, 如下:


import asyncio

async def job():
...
await ...

asyncio.run(job())


多個非同步任務Tasks

「asyncio.create_task( )」 相信這個函式我們常常在原始碼中會常常看到, 而它就是一個更大的非同步單元, 因為我們都知道 await 是一個等待的概念

我們來看底下的例子, 共會需要3秒來完成整個事件,那這樣其實沒有得到非同步應用太大的好處, 我們是希望兩個echo之間是能夠在空閒時切換進行, 節省整體耗時。


import asyncio
import time
async def echo(msg, delay):
await asyncio.sleep(delay)
print(msg)
async def main():
start_time = time.time()
await echo('此作業需要1秒', 1)
await echo('此作業需要2秒', 2)
end_time = time.time()
execution_time = end_time - start_time
print(f'共計 {execution_time} 秒')
asyncio.run(main())


# python test.py
# 此作業需要1秒
# 此作業需要2秒
# 共計 3.003565788269043 秒


因此我們可以針對此情境進行優化, 透過任務的概念, 將兩個任務加入事件循環的Loop, 兩者互不堵塞, 讓任務執行最佳化, 我們可以看到共耗時約2秒左右。


import asyncio
import time
async def echo(msg, delay):
await asyncio.sleep(delay)
print(msg)

async def main():
start_time = time.time()
task1 = asyncio.create_task(
echo('此作業需要1秒', 1))
task2 = asyncio.create_task(
echo('此作業需要2秒', 2))
await task1
await task2
end_time = time.time()
execution_time = end_time - start_time
print(f'共計 {execution_time} 秒')
asyncio.run(main())

# python test.py
# 此作業需要1秒
# 此作業需要2秒
# 共計 2.0014331340789795 秒


結語

本章節主要是簡單的介紹一下Python的非同步概念, 它的精華之處在於讓我們能夠善用每個時刻不浪費, 既然程式語言能夠有這樣的概念, 我們的人生是否就像個事件循環一般呢? 我們是否也能善用這樣的技巧來讓我們的人生更加的精彩且有效率呢?


接下來我們會持續對於非同步協程的部份進行詳細的探討, 讓我們善用協程開發出高效的應用軟體吧!

留言
avatar-img
阿Han的沙龍
157會員
332內容數
哈囉,我是阿Han,是一位 👩‍💻 軟體研發工程師,喜歡閱讀、學習、撰寫文章及教學,擅長以圖代文,化繁為簡,除了幫助自己釐清思路之外,也希望藉由圖解的方式幫助大家共同學習,甚至手把手帶您設計出高品質的軟體產品。
阿Han的沙龍的其他內容
2025/01/29
🤔 簡單且靜態就足夠了? 相信我們在開發Python應用程式的過程中, 常常會借用Enum來定義我們可能的選項, 就像顏色紅、綠、黃會有這樣的結構: class Color(str, Enum): RED = 'red' GREED = 'green' YELLOW = 'yel
Thumbnail
2025/01/29
🤔 簡單且靜態就足夠了? 相信我們在開發Python應用程式的過程中, 常常會借用Enum來定義我們可能的選項, 就像顏色紅、綠、黃會有這樣的結構: class Color(str, Enum): RED = 'red' GREED = 'green' YELLOW = 'yel
Thumbnail
2025/01/08
當我們的系統發展到一定程度時, 難免會面臨到正式上線的問題, 要如何讓維運更加簡易呢? 尤其隨著複雜的客製化配置的出現時, 我們應該如何有效的管理, 甚至驗證配置是否如預期資料型態、格式…, 而正好 pydantic 可以滿足這樣的需求, 就讓我們來看看怎麼使用吧! 需安裝的套件 pip i
Thumbnail
2025/01/08
當我們的系統發展到一定程度時, 難免會面臨到正式上線的問題, 要如何讓維運更加簡易呢? 尤其隨著複雜的客製化配置的出現時, 我們應該如何有效的管理, 甚至驗證配置是否如預期資料型態、格式…, 而正好 pydantic 可以滿足這樣的需求, 就讓我們來看看怎麼使用吧! 需安裝的套件 pip i
Thumbnail
2025/01/02
要如何使用unicorn啟動多個FastAPI服務, 歡迎參考我們的「【💊 Python的解憂錦囊 - FastAPI】如何啟動多個Workers」。 當我們試著設計帶入模組化時… 我們在「【💊 Python的解憂錦囊 - FastAPI】使用 lifespan 來共享資料與管理生命週期
Thumbnail
2025/01/02
要如何使用unicorn啟動多個FastAPI服務, 歡迎參考我們的「【💊 Python的解憂錦囊 - FastAPI】如何啟動多個Workers」。 當我們試著設計帶入模組化時… 我們在「【💊 Python的解憂錦囊 - FastAPI】使用 lifespan 來共享資料與管理生命週期
Thumbnail
看更多
你可能也想看
Thumbnail
背景:從冷門配角到市場主線,算力與電力被重新定價   小P從2008進入股市,每一個時期的投資亮點都不同,記得2009蘋果手機剛上市,當時蘋果只要在媒體上提到哪一間供應鏈,隔天股價就有驚人的表現,當時光學鏡頭非常熱門,因為手機第一次搭上鏡頭可以拍照,也造就傳統相機廠的殞落,如今手機已經全面普及,題
Thumbnail
背景:從冷門配角到市場主線,算力與電力被重新定價   小P從2008進入股市,每一個時期的投資亮點都不同,記得2009蘋果手機剛上市,當時蘋果只要在媒體上提到哪一間供應鏈,隔天股價就有驚人的表現,當時光學鏡頭非常熱門,因為手機第一次搭上鏡頭可以拍照,也造就傳統相機廠的殞落,如今手機已經全面普及,題
Thumbnail
當我們在撰寫一套系統的時候, 總是會提供一個介面讓使用者來觸發功能模組並回傳使用者所需的請求, 而傳統的安裝包模式總是太侷限, 需要個別主機獨立安裝, 相當繁瑣, 但隨著時代的演進與互聯網的崛起, 大部分的工作都可以藉由網頁端、裝置端來觸發, 而伺服端則是負責接收指令、運算與回傳結果, 雲端
Thumbnail
當我們在撰寫一套系統的時候, 總是會提供一個介面讓使用者來觸發功能模組並回傳使用者所需的請求, 而傳統的安裝包模式總是太侷限, 需要個別主機獨立安裝, 相當繁瑣, 但隨著時代的演進與互聯網的崛起, 大部分的工作都可以藉由網頁端、裝置端來觸發, 而伺服端則是負責接收指令、運算與回傳結果, 雲端
Thumbnail
分享一個有趣的套件,名為 await-to-js。 可以讓 Promise 與 await 的寫法更簡潔。
Thumbnail
分享一個有趣的套件,名為 await-to-js。 可以讓 Promise 與 await 的寫法更簡潔。
Thumbnail
當你需要在 Python 中執行多個任務,但又不希望它們相互阻塞時,可以使用 threading 模組。 threading 模組允許你在單個程序中創建多個執行緒,這些執行緒可以同時運行,從而實現並行執行多個任務的效果。
Thumbnail
當你需要在 Python 中執行多個任務,但又不希望它們相互阻塞時,可以使用 threading 模組。 threading 模組允許你在單個程序中創建多個執行緒,這些執行緒可以同時運行,從而實現並行執行多個任務的效果。
Thumbnail
非同步程式設計(Asynchronous programming) 或是簡單的稱之為 async,它是一種並發程式模型(concurrent programming model),其目的就是讓多個任務能同時在作業系統的執行緒上執行,並透過 async/.await 保留同步。
Thumbnail
非同步程式設計(Asynchronous programming) 或是簡單的稱之為 async,它是一種並發程式模型(concurrent programming model),其目的就是讓多個任務能同時在作業系統的執行緒上執行,並透過 async/.await 保留同步。
Thumbnail
前段時間我們有介紹「【Python 軍火庫🧨 - websockets】雙向溝通的渠道」, 這種方式可以達到基本的連線沒問題,但隨著資安意識的抬頭, 我們的websocket連線也會需要在通道之上進行加密, 那麼我們將根據使用情境來教您如何選用適當的連線。 Server端 我們的Serve
Thumbnail
前段時間我們有介紹「【Python 軍火庫🧨 - websockets】雙向溝通的渠道」, 這種方式可以達到基本的連線沒問題,但隨著資安意識的抬頭, 我們的websocket連線也會需要在通道之上進行加密, 那麼我們將根據使用情境來教您如何選用適當的連線。 Server端 我們的Serve
Thumbnail
5 月將於臺北表演藝術中心映演的「2026 北藝嚴選」《海妲・蓋柏樂》,由臺灣劇團「晃晃跨幅町」製作,本文將以從舞台符號、聲音與表演調度切入,討論海妲・蓋柏樂在父權社會結構下的困境,並結合榮格心理學與馮.法蘭茲對「阿尼姆斯」與「永恆少年」原型的分析,理解女人何以走向精神性的操控、毀滅與死亡。
Thumbnail
5 月將於臺北表演藝術中心映演的「2026 北藝嚴選」《海妲・蓋柏樂》,由臺灣劇團「晃晃跨幅町」製作,本文將以從舞台符號、聲音與表演調度切入,討論海妲・蓋柏樂在父權社會結構下的困境,並結合榮格心理學與馮.法蘭茲對「阿尼姆斯」與「永恆少年」原型的分析,理解女人何以走向精神性的操控、毀滅與死亡。
Thumbnail
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
Thumbnail
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
Thumbnail
Websocket是一種網路傳輸的協定,讓建立一次handshake的過程就可以相互傳遞資料,而非同步的過程能夠讓處理事情更有效率,這篇文章將帶你深入瞭解Websocket如何運作、以及其特點與優勢。
Thumbnail
Websocket是一種網路傳輸的協定,讓建立一次handshake的過程就可以相互傳遞資料,而非同步的過程能夠讓處理事情更有效率,這篇文章將帶你深入瞭解Websocket如何運作、以及其特點與優勢。
Thumbnail
簡要說明 JavaScript 的 Event Loop JavaScript 是單執行緒 (single-threaded) 語言,這意味著它一次只能執行一件事,因此所有函式都需要排隊等待執行,這被稱為同步 (synchronous)。在同步操作中,若函式過多或過於複雜,會導致程式阻塞 (blo
Thumbnail
簡要說明 JavaScript 的 Event Loop JavaScript 是單執行緒 (single-threaded) 語言,這意味著它一次只能執行一件事,因此所有函式都需要排隊等待執行,這被稱為同步 (synchronous)。在同步操作中,若函式過多或過於複雜,會導致程式阻塞 (blo
Thumbnail
在網路速度有限的情況下,依序記錄不斷產生的資訊,能統計使用者在頁面上操作了哪些功能。
Thumbnail
在網路速度有限的情況下,依序記錄不斷產生的資訊,能統計使用者在頁面上操作了哪些功能。
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News