[英]How to create non-blocking looping coroutines using python generators?
我正在使用python,我正在嘗試使用生成器作為協同程序。 這意味着我正在使用yield表達式將值傳遞給生成器,然后在各種生成器協同程序之間來回發送消息。
我試圖將協程鏈接到一個迭代一個值的循環,同時保持對源自循環外部的新值的開放。 換句話說,循環應該是非阻塞的:
這是循環:
coroutine_A -> val = (yield) -> does something to val -> coroutine_B.send(other_val)
coroutine_B -> val = (yield) -> does something to val -> coroutine_C.send(other_val)
coroutine_C -> val = (yield) -> does something to val -> coroutine_A.send(other_val)
並且有時我想從這個循環的外部傳遞一個新值到coroutine_A,然后再次關閉它。
EXTERNAL TO LOOP -> coroutine_A.send(message) -> loop continues from new value...
單個部分工作正常,但當我嘗試連接它們時會出現兩個問題。 首先,如何將這些實例化為循環,這似乎是可行的,但會導致更深層次的問題,如下所述。
第一個問題:
在實例化coroutine_A時,coroutine_B尚不存在,因此尚無法告訴coroutine_A它的消息目標是什么。 基本上是雞肉和雞蛋的場景。
我已經嘗試創建一個容器函數來實例化每個協同程序(沒有消息目標),然后創建一個循環來代表協同程序管理消息,如下所示:
def func():
A = coroutine_A()
next(A)
B = coroutine_B()
next(B)
C = coroutine_C()
next(C)
message_A = A.send(None)
while True:
message_B = B.send(message_A)
message_C = C.send(message_B)
message_A = A.send(message_C)
這樣做的問題是,它似乎不可能從循環外傳遞消息,因為while循環只是卡在做它的東西。
另一種方法是使用嵌套的yield表達式實例化coroutine_A,以便在實例化時間之后傳入目標:
def coroutine_A():
while True:
val = (yield)
if val is not None:
coroutine_B_target = val
while True:
val = (yield)
if val is not None:
do something to val
coroutine_B_target.send(other_val)
A = coroutine_A()
next(A) # prime coroutine
A.send(B) # send in coroutine_B target and step into inner while loop
但是,當coroutine_C嘗試向coroutine_A發送消息時,我得到一個ValueError異常:“生成器已經執行”。
因此,這兩種策略基本上都會導致:
更深層次的問題:
似乎作為協同程序的生成器無法自行循環,似乎這樣做的原因是發送調用是一種“正常方法”,因此有效地嘗試將調用堆棧鏈接回自身,即沒有'允許每個David Beazley的Generators:The Final Frontier第127到131頁的遞歸/重新進入。
因此,有必要將信息傳遞給隊列系統,然后出列並開始新的呼叫。 但是當我嘗試這個時,我似乎陷入了阻止源自循環外部的消息的While循環。
所以,長話短說,一方面,一方面如何保持循環自身,而另一方面,如何保持對來自循環外部的新消息保持開放狀態?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.