協(xié)程系列(3) Python asyncio 中的 Future 和 Task
本文將深入探討 Python asyncio 中的 Future 和 Task,為讀者提供對這些核心概念的全面理解。在學(xué)習 asyncio 之前,建議讀者先理解協(xié)程的定義以及 async def 和 await 的基本用法。
asyncio 是 Python 3.4 版本引入的標準庫,它提供了一系列 API,支持異步 I/O、異步網(wǎng)絡(luò)等操作。同時,它也提供了工具,如協(xié)程、任務(wù)和事件循環(huán),以編寫并發(fā)代碼。
asyncio 的實現(xiàn)包含 C 語言加速版本和等效的 Python 實現(xiàn)作為備份,二者在目標上一致,本文將基于易于理解的 Python 實現(xiàn)進行講解。
在 asyncio 中,F(xiàn)uture 是同步代碼與異步代碼之間的橋梁。它記錄任務(wù)的狀態(tài)和結(jié)果或異常,并允許用戶等待結(jié)果或取消任務(wù)。值得注意的是,F(xiàn)uture 具有 `__await__` 方法,當調(diào)用 `await` 時,會觸發(fā)此方法,返回一個生成器,使調(diào)用者等待 Future 的完成。
Task 是 Future 的子類,用于將協(xié)程對象包裝為 Future。Task 的核心邏輯在于 `__step` 方法,它用于執(zhí)行協(xié)程,并處理協(xié)程的完成狀態(tài)。如果協(xié)程拋出 `StopIteration` 異常,說明協(xié)程執(zhí)行完畢,并將結(jié)果設(shè)置到 Future 上。如果協(xié)程產(chǎn)生異常,如被取消或接收到退出信號,將相應(yīng)處理。如果協(xié)程yield出的是一個 asyncio.Future 對象,Task 會將自己加入到該 Future 的完成回調(diào)中。如果yield出的是 None,Task 會將自己加入到事件循環(huán)中。
Task 有三類基本狀態(tài):執(zhí)行中、已完成和已取消。當協(xié)程執(zhí)行完畢或被取消時,Task 會根據(jù)情況進入已完成或已取消狀態(tài)。
在并發(fā)執(zhí)行多個協(xié)程時,`asyncio.gather` 函數(shù)非常實用,它允許用戶同時等待多個協(xié)程的執(zhí)行結(jié)果。使用方法是將所有協(xié)程、生成器或 Future 對象包裝成 Future 對象,并為最終的 `outer` Future 注冊完成回調(diào)。當所有輸入的 Future 對象完成時,`outer` Future 也將完成。
Future 和 Task 在 asyncio 中扮演著至關(guān)重要的角色,它們是同步代碼與異步代碼之間的橋梁。Future 的抽象層次低于 Task,有時僅用于等待 IO 完成或定時器到期等非協(xié)程相關(guān)操作。
本文作者為清華大學(xué)畢業(yè)生,具有 C++/Rust/Python 高級工程師資質(zhì),同時也是 Python 解釋器 CPython 的維護者之一。部分內(nèi)容由 AI 輔助創(chuàng)作。
貳科17866069906: 協(xié)程與函數(shù)線程異步的關(guān)系 -
淄博市鏈輪: ______ 什么協(xié)程 協(xié)程這個概念在計算機科學(xué)里算是一個老概念了,隨著現(xiàn)代計算機語言與多核心處理器的普及,似乎也有普及之勢.協(xié)程是與例程相對而言的. 熟悉C/C++語言的人都知道,一個例程也就是一個函數(shù).當我們調(diào)用一個函數(shù)時,執(zhí)行流...
貳科17866069906: 如何在Python3輸入在第一行給出兩個整數(shù)A和B(?100≤A,B≤100),數(shù)字間以空格分隔 -
淄博市鏈輪: ______ 題目不明,如果要求輸出格式 1,字符串 2,以最小值為起點min(A, B),結(jié)尾為最大值 3,A可能大于等于B 那么,需要用到字符串的乘法,即 "+" * 3 == "+++" 假定B > A,那么就是"A" + " " * (B - A - 1) + "B"
貳科17866069906: 為什么在python3里b=a= -
淄博市鏈輪: ______ 首先,因為你在用C/C++的思維理解python.沒有就是沒有,返回值的提法也不對,返回值是函數(shù)的結(jié)果.準確說應(yīng)該是表達式值.語言的語法是人定義的,賦值是assignment statement,不是expression,所以沒有值.另外,在python里面...
貳科17866069906: 求教python3 selenium3中這個a標簽如何定位 -
淄博市鏈輪: ______ 猜測是有iframe,需要單獨定位移動進去,才能定位
貳科17866069906: Python3.5.2中一個函數(shù)a().有時候不帶括號直接用a.如map(a,「」)這里a什么意思 -
淄博市鏈輪: ______ 我有一個初步理解,但不知道底層細節(jié),python中函數(shù)名也是個變量,可以說你定義的所有名稱都是變量,所有的變量你理解成一個指針,指向一個空間,傳遞名稱則傳遞指針,給其他函數(shù)這個空間的開始.那么這個()呢,在py中有個call方法,你看不到,這個括號會執(zhí)行call,call會運行解釋你的代碼.這樣,一個函數(shù)才算是真正執(zhí)行了.
貳科17866069906: python3.0怎么用json從文件解析 -
淄博市鏈輪: ______ 1、說明: python3通過json模塊load函數(shù)來解析文件. 2、代碼示例: 首先編寫一個json文件j.txt,內(nèi)容如下: {"errno":1,"errmsg":"操作成功!","data":[]} python代碼如下: import json with open('j.txt', 'r') as fr: o = json.load(fr) print(...
貳科17866069906: 在 python 中 A. - apple - at(0,3).size 中size 是什么意思?怎么賦值? -
淄博市鏈輪: ______ size 是返回對象蘋果的屬性,這里看不出來是啥含義,可能是蘋果的大小.
貳科17866069906: python a = 3 b = 3 id(a) == id (b) 結(jié)果是Ture 而把上面 -
淄博市鏈輪: ______ 解釋器在對值很小的int和很短的字符串的時候做了一點小優(yōu)化,只分配了一個對象,讓它們id一樣了.所以a=3的時候相同,當換成(1,2,3)的時候就是兩個不同的對象,所以id會不同.
貳科17866069906: 如何用Python解決OJ中的A+B problem. -
淄博市鏈輪: ______ 描述 Calculate a + b 輸入 Two integer a,,b (0 ≤ a,b ≤ 10) 輸出 Output a + b 樣例輸入 1 2 樣例輸出 3 在python3 中,以這樣的格式輸入兩個數(shù)要把這兩個數(shù)當作一個字符串來處理,找到空格字符,讓后兩個數(shù)相加即可.錯誤解題方法是
貳科17866069906: python3中為什么取消了 -
淄博市鏈輪: ______ 因為python3已經(jīng)可以直接比較大小了,不需要用cmp方法.比如:a=[1,2,3] b=[2,3,4] a>b Out[6]: False aOut[7]: True
asyncio 是 Python 3.4 版本引入的標準庫,它提供了一系列 API,支持異步 I/O、異步網(wǎng)絡(luò)等操作。同時,它也提供了工具,如協(xié)程、任務(wù)和事件循環(huán),以編寫并發(fā)代碼。
asyncio 的實現(xiàn)包含 C 語言加速版本和等效的 Python 實現(xiàn)作為備份,二者在目標上一致,本文將基于易于理解的 Python 實現(xiàn)進行講解。
在 asyncio 中,F(xiàn)uture 是同步代碼與異步代碼之間的橋梁。它記錄任務(wù)的狀態(tài)和結(jié)果或異常,并允許用戶等待結(jié)果或取消任務(wù)。值得注意的是,F(xiàn)uture 具有 `__await__` 方法,當調(diào)用 `await` 時,會觸發(fā)此方法,返回一個生成器,使調(diào)用者等待 Future 的完成。
Task 是 Future 的子類,用于將協(xié)程對象包裝為 Future。Task 的核心邏輯在于 `__step` 方法,它用于執(zhí)行協(xié)程,并處理協(xié)程的完成狀態(tài)。如果協(xié)程拋出 `StopIteration` 異常,說明協(xié)程執(zhí)行完畢,并將結(jié)果設(shè)置到 Future 上。如果協(xié)程產(chǎn)生異常,如被取消或接收到退出信號,將相應(yīng)處理。如果協(xié)程yield出的是一個 asyncio.Future 對象,Task 會將自己加入到該 Future 的完成回調(diào)中。如果yield出的是 None,Task 會將自己加入到事件循環(huán)中。
Task 有三類基本狀態(tài):執(zhí)行中、已完成和已取消。當協(xié)程執(zhí)行完畢或被取消時,Task 會根據(jù)情況進入已完成或已取消狀態(tài)。
在并發(fā)執(zhí)行多個協(xié)程時,`asyncio.gather` 函數(shù)非常實用,它允許用戶同時等待多個協(xié)程的執(zhí)行結(jié)果。使用方法是將所有協(xié)程、生成器或 Future 對象包裝成 Future 對象,并為最終的 `outer` Future 注冊完成回調(diào)。當所有輸入的 Future 對象完成時,`outer` Future 也將完成。
Future 和 Task 在 asyncio 中扮演著至關(guān)重要的角色,它們是同步代碼與異步代碼之間的橋梁。Future 的抽象層次低于 Task,有時僅用于等待 IO 完成或定時器到期等非協(xié)程相關(guān)操作。
本文作者為清華大學(xué)畢業(yè)生,具有 C++/Rust/Python 高級工程師資質(zhì),同時也是 Python 解釋器 CPython 的維護者之一。部分內(nèi)容由 AI 輔助創(chuàng)作。
相關(guān)評說:
淄博市鏈輪: ______ 什么協(xié)程 協(xié)程這個概念在計算機科學(xué)里算是一個老概念了,隨著現(xiàn)代計算機語言與多核心處理器的普及,似乎也有普及之勢.協(xié)程是與例程相對而言的. 熟悉C/C++語言的人都知道,一個例程也就是一個函數(shù).當我們調(diào)用一個函數(shù)時,執(zhí)行流...
淄博市鏈輪: ______ 題目不明,如果要求輸出格式 1,字符串 2,以最小值為起點min(A, B),結(jié)尾為最大值 3,A可能大于等于B 那么,需要用到字符串的乘法,即 "+" * 3 == "+++" 假定B > A,那么就是"A" + " " * (B - A - 1) + "B"
淄博市鏈輪: ______ 首先,因為你在用C/C++的思維理解python.沒有就是沒有,返回值的提法也不對,返回值是函數(shù)的結(jié)果.準確說應(yīng)該是表達式值.語言的語法是人定義的,賦值是assignment statement,不是expression,所以沒有值.另外,在python里面...
淄博市鏈輪: ______ 猜測是有iframe,需要單獨定位移動進去,才能定位
淄博市鏈輪: ______ 我有一個初步理解,但不知道底層細節(jié),python中函數(shù)名也是個變量,可以說你定義的所有名稱都是變量,所有的變量你理解成一個指針,指向一個空間,傳遞名稱則傳遞指針,給其他函數(shù)這個空間的開始.那么這個()呢,在py中有個call方法,你看不到,這個括號會執(zhí)行call,call會運行解釋你的代碼.這樣,一個函數(shù)才算是真正執(zhí)行了.
淄博市鏈輪: ______ 1、說明: python3通過json模塊load函數(shù)來解析文件. 2、代碼示例: 首先編寫一個json文件j.txt,內(nèi)容如下: {"errno":1,"errmsg":"操作成功!","data":[]} python代碼如下: import json with open('j.txt', 'r') as fr: o = json.load(fr) print(...
淄博市鏈輪: ______ size 是返回對象蘋果的屬性,這里看不出來是啥含義,可能是蘋果的大小.
淄博市鏈輪: ______ 解釋器在對值很小的int和很短的字符串的時候做了一點小優(yōu)化,只分配了一個對象,讓它們id一樣了.所以a=3的時候相同,當換成(1,2,3)的時候就是兩個不同的對象,所以id會不同.
淄博市鏈輪: ______ 描述 Calculate a + b 輸入 Two integer a,,b (0 ≤ a,b ≤ 10) 輸出 Output a + b 樣例輸入 1 2 樣例輸出 3 在python3 中,以這樣的格式輸入兩個數(shù)要把這兩個數(shù)當作一個字符串來處理,找到空格字符,讓后兩個數(shù)相加即可.錯誤解題方法是
淄博市鏈輪: ______ 因為python3已經(jīng)可以直接比較大小了,不需要用cmp方法.比如:a=[1,2,3] b=[2,3,4] a>b Out[6]: False aOut[7]: True