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コルーチン(yield-based)は本物です(他と比べてみると…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()は一時停止したジェネレーターを再開します。実行中のジェネレーターでそれらを呼び出すと、例外が発生します。

(の特定の 1 つのインスタンスgv2を表す)にアクセスしているのはなぜですか? ジェネレーターは自己完結型である必要があり、その使用方法について何の仮定もしてはなりません。他のスコープからジェネレーターを呼び出すことにした場合はどうなりますか? いずれにせよ、値を自分自身に送信しても意味がありません。値は既に持っています。test2test2()

于 2012-08-06T14:50:40.793 に答える