Coroutines: unexpected behaviour
Thomas Jollans
thomas at jollans.com
Wed Jun 16 08:35:10 EDT 2010
On 06/16/2010 02:03 PM, Jérôme Mainka wrote:
> Hello,
>
> I try to experiment with coroutines and I don't understand why this
> snippet doesn't work as expected... In python 2.5 and python 2.6 I get
> the following output:
>
> 0
> Exception exceptions.TypeError: "'NoneType' object is not callable" in
> <generator object at 0x7e43f8> ignored
>
> The TypeError exception comes from the pprint instruction...
>
> If i replace the main part with:
>
> ==
> p1 = dump()
> p2 = sort(p1)
> for item in my_list: p2.send(item)
> ==
>
> it works as expected.
What a strange problem. I hope somebody else can shed more light on what
is going on
Anyway, it appears (to me) to be a scoping issue: if you move
"from pprint import pprint" into the dump() function body, it works. I
don't understand why this changes anything: pprint was in the global
namespace all along, and it's present and functioning exactly *once*,
after which it's None. It's still there, otherwise there'd be a
NameError, but it was set to None without any line of code doing this
explicitly as far as I can see.
Another VERY strange thing is, of course, your "fix": renaming "p" to
"p2" helps. "p", "p1", "p3", and "yyy" are just some examples of
variable names that don't work.
As for Python versions: I changed the code to work with Python 3 and get
the same odd behaviour.
>
> I don't understand what is goind wrong. Has someone an explanation for
> this issue?
>
> Thanks,
>
> Jérôme
>
>
> ===
> from functools import wraps
> from pprint import pprint
> import random
>
> def coroutine(f):
> @wraps(f)
> def start(*args, **kwargs):
> res = f(*args, **kwargs)
> res.next()
> return res
> return start
>
> @coroutine
> def sort(target):
> l = []
>
> try:
> while True:
> l.append((yield))
> except GeneratorExit:
> l.sort()
> for item in l:
> target.send(item)
>
> @coroutine
> def dump():
> while True:
> pprint((yield))
>
> if __name__ == "__main__":
> my_list = range(100)
> random.shuffle(my_list)
>
> p = sort(dump())
>
> for item in my_list:
> p.send(item)
More information about the Python-list
mailing list