I was implementing greenlet API just for practicing.
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()
here’s my messy code
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)
Shows,
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
So, I don’t know I guess correctly,
but It looks that after test1 send ‘1’ to test2, it still has something,
no control-flow switching happens unlike gevent. test1 still have the flow.
if not, I don’t understand what greenlet can do but python “coroutine” can’t exists.
My question is
- is python coroutine(yield-based) is the real thing(comparing it of others…lisp,ruby,&c)
- if right, would you please give some tips for that spagetti code?
The generator instance of
test2()is sending a value to itself.send()will resume the generator, but whenever code is executed insidetest2(), it is already running. That is why it throws up.Did you want to do:
gv1.send(1)? That would not work either.Here is why:
gv1.send(1)at the very end of your examplegv1.send(1)is invoked, this resumesgv1gv1proceeds togv2.send(1)gv2gv2proceeds togv1.send(1)gv1is being resumed, however,gv1has not reached ayieldstatement since it was last resumed. Ergo, it is still running, which is why it would also throw.Essentially, the difference could be summarized like this:
.switch()pauses the currently executing greenlet and will resume however.yieldwill “pause” a generatornext()/send()will resume a paused generator, invoking them on running generators will result in an exception.Why are you accessing
gv2(which represents one particular instance oftest2) at all? The generatortest2()should be self-contained and not make any assumptions about how it is being used. What if you decide, that you want to invoke the generator from some other scope? It doesn’t make any sense to send values to yourself anyway: You already have them.