gpt4 book ai didi

python - 如何使用 python 生成器创建非阻塞循环协程?

转载 作者:行者123 更新时间:2023-11-28 19:19:16 25 4
gpt4 key购买 nike

我正在使用 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 异常:“generator already executing”。

所以这两种策略基本上都会导致:

更深层次的问题:

作为协程的生成器似乎无法循环回自身,似乎其原因是发送调用是一种“普通方法”,因此有效地尝试将调用堆栈链接回自身,即根据 David Beazley 的 Generators: The Final Frontier 不允许递归/重新进入第 127 至 131 页。

因此有必要将信息移交给队列系统,然后出队并开始新的调用。但是当我尝试这样做时,我似乎陷入了 While 循环,它阻止了来自循环外部的消息。

那么,长话短说,如何一方面保持循环自发运转,另一方面又对来自循环外部的新消息保持开放?

最佳答案

关于python - 如何使用 python 生成器创建非阻塞循环协程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29165182/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com