1

I've been using generator based coroutines before the asyncio was released.

Now I'm trying to learn the new async/await features introduced in Python 3.5. This is one of my test programs.

class Await3:
    def __init__(self, value):
        self.value = value
    def __await__(self):
        return iter([self.value, self.value, self.value])

async def main_coroutine():
    x = await Await3('ABC')
    print("x =", x)

def dummy_scheduler(cobj):
    snd = None
    try:
        while True:
            aw = cobj.send(snd)
            #snd = 42
            print("got:", aw)
    except StopIteration:
        print("stop")

dummy_scheduler(main_coroutine())

Its output is:

got: ABC
got: ABC
got: ABC
x = None
stop

The value of x is the result of await awaitable_object expression. Why is this value None and how can I set it to a value I want?

All I could find is that value of await couroutine() is determined by the coroutine's return value, but that's not my case.

Uncommenting snd = 42 does not work. The error is AttributeError: 'list_iterator' object has no attribute 'send'

VPfB
  • 14,927
  • 6
  • 41
  • 75

1 Answers1

2

If you're going to implement a class with an __await__ method manually, the return value of an await expression on an instance of your class will be whatever argument was used to construct the StopIteration exception at the end of the iterator, or None if there was no argument.

You can't control the StopIteration argument with something like return iter(some_list). You need to write your own iterator. I'd say to write it as a generator and return the value:

class Await3:
    def __init__(self, value):
        self.value = value
    def __await__(self):
        yield self.value
        yield self.value
        yield self.value
        return whatever

which will throw StopIteration(whatever) to end the iteration, but if you wanted to do things the easy way, you would have written an async function in the first place.

user2357112
  • 260,549
  • 28
  • 431
  • 505