![](/img/trans.png)
[英]Python/Erlang: What's the difference between Twisted, Stackless, Greenlet, Eventlet, Coroutines? Are they similar to Erlang processes?
[英]Are Python coroutines stackless or stackful?
關於 Python 協程(我主要是指async/await
)是無堆棧還是堆棧,我看到了相互矛盾的觀點。
一些消息來源說他們堆積如山:
“Python 協程堆積如山。”
是的,Python 協程是堆疊的、一流的和不對稱的。
雖然其他人似乎暗示他們是無堆棧的,例如https://gamelisp.rs/reference/coroutines.html
GameLisp 的協程遵循 Rust、Python、C# 和 C++ 設置的 model。我們的協程是“無堆棧”的
總的來說,我的理解總是任何有意義的異步/等待實現都意味着無堆棧協程,而堆棧協程基本上是纖程(用戶空間線程,通常或多或少地協同切換),比如 goroutines、Boost.Coroutine,顯然是 Lua 等。
我的理解正確嗎? 或者 Python 協程是否與 C++ 中的協程有某種根本的不同,並且是堆疊的? 還是上述來源的作者有不同的意思?
TLDR:按照C++ 的定義, Python 的協程也是無堆棧的。 定義特征是協程的持久化 state 與堆棧分開存儲。
協程是無堆棧的:它們通過返回調用者來暫停執行,恢復執行所需的數據與堆棧分開存儲。 […]
在技術層面上,Python 需要await
、 async for
等,以允許子協程掛起它們的父協程。 定期調用 function 是不可能掛起其父級的。
async def foo():
a = await some_awaitable() # this may suspend `foo` as well
b = some_function() # this cannot suspend `foo`
return a + b
與無堆棧協程相比,堆棧協程可以從嵌套堆棧框架中暫停。 ( 提升:協程)
堆棧和協程的交互不像常規例程那樣清晰。 例程正在執行或完成。 這自然映射到 function 執行,將單個執行幀添加到堆棧; 1一旦該幀完成例程完成,幀從堆棧中彈出並丟棄。
相反,協程可以是 executing 、 suspended或 done 。 這就提出了一個問題,即如何在暫停期間處理 state——實際上,如何處理局部變量。 突出的手段有兩種:
我們可以將每個部分執行視為常規例程。 為了獲得協程語義,當這樣的例程完成時,我們保護它的 state。這允許我們在各個協程之間切換。
我們可以將整個執行過程視為常規例程。 為了獲得協程語義,當這樣的例程掛起時,我們保護整個堆棧。 這允許我們在各個堆棧之間切換。
解決方案 1. 通常稱為無堆棧——協程獨立於堆棧。 這提供了很多功能,因為每個步驟都是一流的,但它暴露了很多實現細節。 我們必須顯式地模擬嵌套協程執行的堆棧——通常,這就是await
的作用。
解決方案 2. 通常稱為stackfull——協程作為堆棧本身的一部分存在。 由於執行在內部發生,因此這消除了很多功能,但隱藏了很多實現細節。 例程與協程的區別是隱藏的,甚至是無關緊要的——任何例程都可以在任何時候暫停。
這些定義不是通用的。 例如,您可能會發現 1. 被稱為 stackfull,因為協程本身保留了自己的暫停堆棧。 如有疑問,請比較語義而不是命名。
然而,這似乎是最普遍的命名方案(請參閱參考資料)。
從技術角度來看, Python 的協程是無棧的。 協程函數創建一流的協程對象,允許部分執行並在掛起期間在內部存儲 state( 作為cr_frame
)。 協程是使用顯式await
嵌套的,例程不能await
任何東西。
值得注意的是,Python 本身不支持堆棧協程:常規例程無法暫停執行。 2個
1幀堆棧的語義並不一定意味着實現具有 function 執行與 memory 堆棧上的幀的 1:1 關系。 相反,將“堆棧”視為運行時的抽象描述,可以通過 function 執行來定義。 實現可能會有所不同,但對語言的高級語義沒有可觀察到的差異。 考慮 CPython,它有一個運行 Python 堆棧的 C 堆棧。
2 stackfull協程的缺失不是由語言語義嚴格保證的。 有第三方擴展可以添加 stackfull 協程,即greenlet 。 恰好,這是由Stackless Python引入的——“Stackless”指的是解釋器對 C-Stack 的使用,而不是協程如何使用堆棧。
然而,這是一個獨立於 Python 自身的await
和yield
暫停的暫停機制。
參考:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.