[Python-Dev] Coroutines and PEP 380
Mark Shannon
mark at hotpy.org
Tue Jan 17 23:03:45 CET 2012
Hi all.
Lets start controversially: I don't like PEP 380, I think it's a kludge.
I think that CPython should have proper coroutines, rather than add more
bits and pieces to generators in an attempt to make them more like
coroutines.
I have mentioned this before, but this time I have done something about
it :)
I have a working, portable, (asymmetric) coroutine implementation here:
https://bitbucket.org/markshannon/hotpy_coroutines
Its all standard C, no messing with the C stack, just using standard
techniques to convert recursion to iteration
(in the VM not at the Python level) and a revised internal calling
convention to make CPython stackless:
https://bitbucket.org/markshannon/hotpy_stackless
Then I've added a Coroutine class and fiddled with the implementation of
YIELD_VALUE to support it.
I think the stackless implementation is pretty solid, but the
coroutine stuff needs some refinement.
I've not tested it well (it passes the test suite, but I've added no new
tests).
It is (surprisingly) a bit faster than tip (on my machine).
There are limitations: all calls must be Python-to-Python calls,
which rules out most __xxx__ methods. It might be worth special casing
__iter__, but I've not done that yet.
To try it out:
>>> import coroutine
To send a value to a coroutine:
>>> co.send(val)
where co is a Coroutine()
To yield a value:
>>> coroutine.co_yield(val)
send() is a method, co_yield is a function.
Here's a little program to demonstrate:
import coroutine
class Node:
def __init__(self, l, item, r):
self.l = l
self.item = item
self.r = r
def make_tree(n):
if n == 0:
return Node(None, n, None)
else:
return Node(make_tree(n-1), n, make_tree(n-1))
def walk_tree(t, f):
if t is not None:
walk_tree(t.l, f)
f(t)
walk_tree(t.r, f)
def yielder(t):
coroutine.co_yield(t.item)
def tree_yielder(t):
walk_tree(t, yielder)
co = coroutine.Coroutine(tree_yielder, (make_tree(2),))
while True:
print(co.send(None))
Which will output:
0
1
0
2
0
1
0
None
Traceback (most recent call last):
File "co_demo.py", line 30, in <module>
print(co.send(None))
TypeError: can't send to a halted coroutine
Cheers,
Mark.
More information about the Python-Dev
mailing list