pythonasync-await

Creating __await__() from another awaitable object


I was experimenting with creating my own awaitable object. I understand that the precise details of what __await__ returns are async-library dependent, but I was hoping I could just copy the values from another asynchronous function.

import asyncio

class MyObject:
    async def ten(self):
        await asyncio.sleep(.5)
        print("Returning")
        return 10

    def __await__(self):
         # Just do exactly what ten() does
        yield from self.ten().__await__()
retu

async def main():
    object = MyObject()
    print(await object.ten())
    print(await object)


if __name__ == '__main__':
    asyncio.run(main())

When I ran the code, both await object.ten() and await object paused for half a second and then printed the message. But the former returned the value 10 while the latter returned None.

Is it possible to craft a generic __await__ function that behaves exactly like another asynchronous function, including its return value?


Solution

  • Yes, you just forgot return:

        def __await__(self):
             # Just do exactly what ten() does
            return (yield from self.ten().__await__())
    

    This is the classic way, and return (yield from awaitable.__await__()) is equivalent to return await awaitable in an asynchronous function. Alternatively, you can do it this way:

        def __await__(self):
             # Just do exactly what ten() does
            return self.ten().__await__()
    

    But then your __await__() will not appear in stack traces, making it harder to debug for errors.