Coroutines: unexpected behaviour

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Wed Jun 16 12:35:30 EDT 2010


On Wed, 16 Jun 2010 05:03:13 -0700, 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

I changed the while loop in dump() to print the value of pprint:

    while True:
        print type(pprint), pprint
        pprint((yield))


and sure enough I get this output:

[steve at sylar ~]$ python2.6 test_coroutine.py
<type 'function'> <function pprint at 0xb7edc534>
0
<type 'NoneType'> None
Exception TypeError: "'NoneType' object is not callable" in <generator 
object sort at 0xb7ee5c84> ignored


BUT then I wrapped the __main__ code in a function:


def f():
    my_list = range(100)
    random.shuffle(my_list)
    p = sort(dump())
    for item in my_list:
        p.send(item)

if __name__ == "__main__":
    f()


and the problem went away:

[steve at sylar ~]$ python2.6 test_coroutine.py
<type 'function'> <function pprint at 0xb7eb44fc>
0
<type 'function'> <function pprint at 0xb7eb44fc>
1
<type 'function'> <function pprint at 0xb7eb44fc>
2
[...]
<type 'function'> <function pprint at 0xb7eb44fc>
99
<type 'function'> <function pprint at 0xb7eb44fc>


How bizarre is that?


I have to say that your code is horribly opaque and unclear to me. Maybe 
that's just because I'm not familiar with coroutines, but trying to 
follow the program flow is giving me a headache. It's like being back in 
1977 trying to follow GOTOs around the code, only without line numbers. 
But if I have understood it correctly, I think the generator function 
coroutine(sort) is being resumed by both the send() method and the next() 
method. I draw your attention to this comment from the PEP that 
introduced coroutines:


[quote]
Because yield will often be returning None, you should always check for 
this case. Don't just use its value in expressions unless you're sure 
that the send() method will be the only method used resume your generator 
function.
[end quote]

http://docs.python.org/release/2.5/whatsnew/pep-342.html


So I wonder if that has something to do with it?



-- 
Steven



More information about the Python-list mailing list