如何搭配

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




o = await api.open()


在一个功能?

因为第一个要求对象带有__aenter____aexit__,但是第二个要求__await__,它应该是不带await的生成器。

我的尝试是:

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()


但是,如果用__await__aenter)定义了async def,则对TypeError: cannot 'yield from' a coroutine object in a non-coroutine generator失败。

它对于@asyncio.coroutineaenter装饰器可以正常工作,但这很脏。

最佳答案

您可以从课程的__aenter__返回__await____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()


输出:

enter
hello
exit
enter

10-01 06:30