2015-12-02 21 views
5

Jak mieszaćMixinig asynchroniczny kierownik kontekst i prosto czekają asyncio

async with api.open() as o: 
    ... 

i

o = await api.open() 

w jednej funkcji?

Ponieważ pierwszy wymagają obiekt z __aenter__ i __aexit__, ale drugi wymaga __await__, który powinien być generator bez await.

Moja próba była:

def AsyncContext(aenter, aexit): 

    class AsyncContextClass: 

     async def __aenter__(self): 

      return await aenter() 

     async def __aexit__(self, *args): 

      return await aexit(*args) 

     def __await__(self): 

      return (yield from aenter()) 

    return AsyncContextClass() 

Ale nie jest on z __await__ jeśli aenter zdefiniowanej z async def (TypeError: cannot 'yield from' a coroutine object in a non-coroutine generator).

Działa dobrze z dekoratorem @asyncio.coroutine dla aenter, ale to jest "brudne".

Odpowiedz

10

Możesz powrócić __aenter__ „s __await__ z twojej klasy na __await__:

# vim: tabstop=4 expandtab 

import asyncio 

class Test(object): 

    async def __aenter__(self): 
     print("enter") 

    async def __aexit__(self, *args): 
     print("exit") 

    def __await__(self): 
     return self.__aenter__().__await__() 

async def run(): 
    async with Test(): 
     print("hello") 

    await Test() 

loop = asyncio.get_event_loop() 
loop.run_until_complete(run()) 
loop.close() 

wyjściowa:

enter 
hello 
exit 
enter