Use await with object that implements the __await__

0

From Python 3.5 was entered async/await I'm implementing some objects that are waiting but I'm encountering doubts follow an example:

#!usr/bin/python3                                                                         
# -*- coding: utf-8 -*-                                                                   

import asyncio                                                                            


class Waiting:                                                                      

    def __await__(self):                                                                  
        print('__await__')                                                                
        yield from asyncio.sleep(3)                                                       
        print('Ok')                                                                       


async def main():                                                                         
    await Waiting()                                                                       


if __name__ == '__main__':                                                                
    loop = asyncio.get_event_loop()                                                       
    try:                                                                                  
        loop.run_until_complete(main())                                                   
    finally:                                                                              
        loop.close() 

If the script is executed the result will be:

__await__
Ok

Sure the script worked, but if you try to implement it using the new reserved words from Python 3.5 I run into an error, follow the script:

#!usr/bin/python3                                                                         
# -*- coding: utf-8 -*-  



import asyncio                                                                            

class Waiting:                                                                      

    async def __await__(self):                                                            
        print('__await__')                                                                
        await asyncio.sleep(3)                                                            
        print('Ok')

async def main():                                                                         
    await Waiting() 




if __name__ == '__main__':                                                                
    loop = asyncio.get_event_loop()                                                       
    try:                                                                                  
        loop.run_until_complete(main())                                                   
    finally:                                                                              
        loop.close() 

I made __await__ a co-routine and changed yield from to await and now when I run the script I get:

Traceback (most recent call last):
  File "dunder_await.py", line 22, in <module>
    loop.run_until_complete(main())
  File "/usr/lib/python3.6/asyncio/base_events.py", line 468, in run_until_complete
    return future.result()
  File "dunder_await.py", line 16, in main
    await Waiting()
TypeError: __await__() returned a coroutine

Correct me if I am wrong but for me to use await do I have to define a co-routine and await should work as yield from or am I wrong? And why am I getting this error?

    
asked by anonymous 14.08.2018 / 08:10

1 answer

2

The magic function __await__ is for you to create a " flashy " object in the same way as the new reserved word async def ... That is, if you use __await__ you do not need to use async def :

class AsyncFunction:
    def __await__(self):
        ...
x = AsyncFunction()
await x

is the same as:

async def AsyncFunction():
    ...
x = AsyncFunction()
await x

So in your example you have to choose. Either define a function with async def or create a class with __await__ , both serve the same thing but should not be used together.

    
14.08.2018 / 19:57