python / asyncio

asyncio historical repository
https://docs.python.org/3/library/asyncio.html
1.04k stars 177 forks source link

loop.set_debug(True) makes "TypeError: __await__() returned a coroutine" disappear #451

Open diefans opened 7 years ago

diefans commented 7 years ago

My python version is 3.5.2

The following example illustrates the problem:


import asyncio

class Foo:
    async def __await__(self):
        return "Foo"

async def run_foo():
    foo = Foo()
    return await foo

if __name__ == '__main__':
    for debug in (False, True):
        loop = asyncio.new_event_loop()
        loop.set_debug(debug)

        print("debug =", debug, "results in:", end=" ")
        try:
            result = loop.run_until_complete(run_foo())
            print(result)

        except TypeError as ex:
            print(ex)

        loop.close()
debug = False results in: __await__() returned a coroutine
debug = True results in: Foo

This behaviour was indeed surprising when I begun to work and experiment with asyncio, where most of the time I enabled debug, but in unit testing then disabled it...

I am wondering, if the TypeError for a coroutine returned by await() enforced by https://www.python.org/dev/peps/pep-0492/#await-expression is really necessary. Btw to use await syntax in await I always return the result of the await method of an inner coroutine, e.g.:

class Foo:
    def __await__(self):
        async def coro():
            return await self.something()
        return coro().__await__()
1st1 commented 7 years ago

This is a bug in CoroWrapper.

I am wondering, if the TypeError for a coroutine returned by await() enforced by https://www.python.org/dev/peps/pep-0492/#await-expression is really necessary.

It is necessary. __await__ requires an iterator and coroutines don't implement iterator protocol (because casting a coroutine in, let's say, tuple, doesn't make any sense).

1st1 commented 7 years ago

To properly fix this, we'll need to split CoroWrapper class in two -- one for generator-based coroutines, and one for async/await coroutines. This is something that can break a lot of things, so let's wait until 3.7.