python – 基于产量的协程是真正的协同程序吗?

我正在实施greenlet API.

from greenlet import greenlet

def test1():
    print 12
    gr2.switch()
    print 34

def test2():
    print 56
    gr1.switch()
   print 78

gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch()

这是我凌乱的代码

def test1():
    tmp1=yield
    print 12
    try:
        gv2.send(1)
    except StopIteration:
        pass
    tmp1=yield
    print 34

def test2():
    tmp2=yield
    print 56
    try:
        gv2.send(1)
    except StopIteration:
        pass
    tmp1=yield
    print 78

gv1=test1()
gv1.next()
gv2=test2()
gv2.next()

gv1.send(1)

可见,

12
56
Traceback (most recent call last):
  File "prog.py", line 26, in <module>
    gv1.send(1)
  File "prog.py", line 5, in test1
    gv2.send(1)
  File "prog.py", line 15, in test2
    gv2.send(1)
ValueError: generator already executing

所以,我不知道我猜对了,

但看起来在test1发送’1’到test2后,它仍然有一些东西,

与gevent不同,没有控制流切换发生. test1仍有流量.

如果没有,我不明白greenlet可以做什么,但python“coroutine”不能存在.

我的问题是

>是python协程(基于产量)是真实的东西(比较其他人… lisp,ruby,& c)
>如果正确的话,请你提供一些关于spagetti代码的提示吗?

最佳答案 test2()的生成器实例正在向自身发送一个值.

def test2():
    tmp2=yield
    print 56
    try:
        gv2.send(1) # this is the offending line
    except StopIteration:
        pass
    tmp1=yield
    print 78

send()将恢复生成器,但只要代码在test2()中执行,它就已经在运行了.这就是它抛出的原因.

你想做什么:gv1.send(1)?这也行不通.

原因如下:

>当前情况:在你的例子最后的gv1.send(1)之前

> gv1处于休眠状态
> gv2处于休眠状态

> gv1.send(1)被调用,这将恢复gv1
> gv1进入gv2.send(1)
>这将恢复gv2
> gv2进入gv1.send(1)
> gv1正在恢复,但是,gv1自上次恢复以来尚未达到yield语句.因此,它仍在运行,这就是为什么它也会抛出.

从本质上讲,差异可以总结如下:

> greenlets彼此共享一个固有的连接:.switch()暂停当前正在执行的greenlet,然后将恢复.
另一方面,>发电机完全相互独立.没有执行生成器的共享上下文.

> yield将“暂停”一台发电机
> next()/ send()将恢复暂停的生成器,在运行的生成器上调用它们将导致异常.

你为什么要访问gv2(它代表一个特定的test2实例)呢?生成器test2()应该是独立的,不要对它的使用方式做任何假设.如果您决定要从其他范围调用生成器,该怎么办?无论如何向自己发送价值是没有任何意义的:你已经拥有它们.

点赞