2

我可以连接两个协程 A 和 B,A 会激发 B,B 会激发 A?例如,A 将接受一个数字,打印它并使用 (number+1) 调用 B。B 将打印它并使用 (number+1) 调用 A。我希望 1,2,3,4,5,... 打印

不幸的是,这段代码确实按预期工作

def coroutine(func):
    def start(*args,**kwargs):
        cr = func(*args,**kwargs)
        cr.next()
        return cr
    return start

_target_from_a = None
_target_from_b = None

@coroutine
def func_a():
    while True:
        item = yield
        print 'a', item
        _target_from_a.send(item + 1)

@coroutine
def func_b():
    while True:
        item = yield
        print 'b', item
        _target_from_b.send(item + 1)

a = func_a()
b = func_b()
_target_from_a = b
_target_from_b = a

a.send(1)

它产生以下错误

a 1
b 2
Traceback (most recent call last):
  File "coloop.py", line 31, in <module>
    a.send(1)
  File "coloop.py", line 17, in func_a
    _target_from_a.send(item + 1)
  File "coloop.py", line 24, in func_b
    _target_from_b.send(item + 1)
ValueError: generator already executing
4

1 回答 1

2

当您执行_target_from_a.send(something)a程时,在被恢复执行的yield调用“暂停”之前b,它的作用是:

    item = yield
    print 'b', item
    _target_from_b.send(item + 1)   # ARGH!!

问题是_target_from_b.send(item + 1)会尝试调用a. 但a在这一瞬间,它并没有等待任何东西,它还在执行。

请记住,协程在执行时就像任何其他函数一样。调用_target_from_a.send()不会暂停协程,python 只是简单地执行函数调用。

总结:永远不要用协程做循环。他们根本无法工作。

请注意,generator already executing从多个线程访问同一个生成器/协程时也可能引发异常。


我建议你阅读David Beazley的“A Curious Course on Coroutines and Concurrency”,他很好地解释了应该如何使用协程以及它们是如何工作的。

于 2013-05-24T11:04:57.550 回答