3

我只是为了练习而实现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“协程”不存在。

我的问题是

  1. 是python协程(基于产量)是真实的东西(与其他人比较......lisp,ruby,&c)
  2. 如果是的话,请您提供一些意大利面条代码的提示吗?
4

1 回答 1

7

的生成器实例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因此,它仍在运行,这就是它也会抛出的原因。

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

  • greenlet彼此共享一个固有的连接:.switch()暂停当前正在执行的 greenlet,但会继续。
  • 另一方面,生成器彼此完全独立。没有执行生成器的共享上下文。
    • yield将“暂停”发电机
    • next()/send()将恢复暂停的生成器,在正在运行的生成器上调用它们将导致异常。

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

于 2012-08-06T14:50:40.793 回答