当没有引用 'await' 时,其 finally 块中没有 'await' 的异步生成器是否会立即关闭?

Will async-generators that don't have 'await' in its finally-block be immediately closed when there is no reference to it?

提问人:Nattōsai Mitō 提问时间:10/26/2020 最后编辑:Nattōsai Mitō 更新时间:10/29/2020 访问量:769

问:

根据这篇博客,当没有参考时,普通发电机将立即关闭。(CPython 独家)。我的问题是“这是否适用于在其最终块中没有”await“的异步生成器?

赋予动机

我是异步库的专家,希望异步生成器像普通生成器一样工作。否则,用户必须编写如下代码

    agen = async_generator_function()
    async with async_closing(agen):
        async for v in agen:
            if some_condition:
                break
            do_something()

取而代之的是这个

    async for v in async_generator_function():
        if some_condition:
            break
        do_something()

这很烦人。幸运的是,它的单元测试总是像我预期的那样工作,所以我想知道它是否得到保证。

调查

以下代码

import asyncio

async def agen_func():
    try:
        for i in range(10):
            yield i
    finally:
        print('finalized')

async def main():
    async for i in agen_func():
        print(i)
        if i > 2:
            break
    print('end of main()')

asyncio.run(main())

印刷

0
1
2
3
end of main()
finalized

和下面的代码

import trio

async def agen_func():
    try:
        for i in range(10):
            yield i
    finally:
        print('finalized')

async def main():
    async for i in agen_func():
        print(i)
        if i > 2:
            break
    print('end of main()')

trio.run(main)

打印相同的,看起来两者都像,并对我的问题说“不”,因为如果异步生成器像我预期的那样立即关闭,它们就会在之前打印.实际上,如果您使用这两个异步库,我问题的答案可能是“否”。asynciotriofinalizedend of main()

但这里有一件有趣的事情。如果你不使用它们,异步生成器会按我的预期工作。

async def agen_func():
    try:
        for i in range(10):
            yield i
    finally:
        print('finalized')


async def main():
    async for i in agen_func():
        print(i)
        if i > 2:
            break
    print('end of main()')


try:
    main().send(None)
except StopIteration:
    pass
0
1
2
3
finalized
end of main()

这就是我目前正在开发的异步库的工作方式。

set_asyncgen_hooks

根据 PEP525 的说法,做了一些叫做 . 也是。我相信这就是异步生成器在它们下无法像我预期的那样工作的原因。这是可以理解的,因为它对于其 finally-block 包含 .asynciosys.set_asyncgen_hooks()trioawait

更精确的问题

所以我的问题是:

如果你使用的是 CPython,而你使用的异步库没有做上面的 hacky 事情,那么当没有引用它时,没有在其 finally-block 中的异步生成器将立即关闭?await

环境

  • CPython 3.8.1 版本
  • 三重奏 0.17.0
python-3.x 异步 cpython

评论


答: 暂无答案