作者:默思編輯部 發布:2026-05-16
asyncio.gather() 長期是 Python 開發者處理多個並行非同步任務的預設工具,但它有一個容易被忽略的風險:當其中一個任務拋出例外時,gather 不會自動取消其他還在執行中的任務——這代表程式可能會留下一堆「孤兒任務」(orphaned tasks)繼續在背景執行,卻沒有人在管理它們的生命週期,可能造成資源洩漏或難以預期的副作用。
asyncio.TaskGroup(Python 3.11 引入)採用了「結構化並行」(structured concurrency)的設計理念,核心規則很直觀:一個任務的生命週期,被綁定在它所屬的程式區塊(lexical scope)內,而不是綁定在某個可能活得比原本目的更久的全域事件迴圈上。
具體運作方式:透過 async with TaskGroup() 進入一個範圍,範圍內用 create_task() 建立的所有任務,都被綁定在這個 TaskGroup 的生命週期內。當這個範圍結束時——不管是正常結束、拋出例外,還是被取消——範圍內所有還沒完成的任務,都會被自動取消,確保不會有任務被遺忘在背景裡。
TaskGroup 相較 gather 提供了更強的安全保證:只要群組裡任何一個任務(或它衍生出的子任務)拋出例外,TaskGroup 會立刻取消其餘所有還在執行的任務並等待它們結束;而 gather 則不會有這種行為。當例外真的發生時,TaskGroup 會把所有相關的例外,統一包裝成一個 ExceptionGroup(例外群組)一次拋出——這代表就算同時有多個任務失敗,你也能一次看到所有的錯誤訊息,而不是像 gather 只回報第一個遇到的錯誤,其他錯誤訊息就這樣被吞掉。
如果你的專案已經在使用 Python 3.11 以上版本,2026 年的業界共識很明確:優先使用 TaskGroup 而非 gather。理由很直接——TaskGroup 有更完整的錯誤語意(一次拿到所有錯誤,而不只是第一個),而且它代表的是 Python 並行程式設計往後發展的方向,是目前語言演進在鼓勵的寫法。
對於用 Python 開發需要同時處理多個非同步任務的應用(例如同時呼叫多個 API、平行處理多個檔案),改用 TaskGroup 不只是跟上最新語法潮流,更實質地降低了「任務洩漏」與「錯誤被靜默吞掉」這兩類難以除錯的隱藏 bug 風險——尤其是在正式環境的長時間運行服務裡,這種結構化保證的價值會隨著系統複雜度增加而愈來愈明顯。