Nat*_*itō 8 asynchronous cpython python-3.x
根据这个博客,正常的生成器在没有引用时会立即关闭。(不过是 CPython 独有的)。我的问题是“这是否适用于在 finally 块中没有‘await’的异步生成器?”
我是一个异步库的作者,并希望异步生成器像普通的一样工作。否则,用户必须编写这样的代码
agen = async_generator_function()
async with async_closing(agen):
async for v in agen:
if some_condition:
break
do_something()
Run Code Online (Sandbox Code Playgroud)
而不是这个
async for v in async_generator_function():
if some_condition:
break
do_something()
Run Code Online (Sandbox Code Playgroud)
这很烦人。幸运的是,它的单元测试总是按我的预期工作,所以我想知道它是否有保证。
以下代码
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())
Run Code Online (Sandbox Code Playgroud)
打印
0
1
2
3
end of main()
finalized
Run Code Online (Sandbox Code Playgroud)
以及以下代码
0
1
2
3
end of main()
finalized
Run Code Online (Sandbox Code Playgroud)
打印了相同的内容,看起来两者都一样,asyncio
并且trio
对我的问题说“不”,因为如果异步生成器按照我的预期立即关闭,它们会finalized
在end 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
Run Code Online (Sandbox Code Playgroud)
0
1
2
3
finalized
end of main()
Run Code Online (Sandbox Code Playgroud)
这就是我目前正在开发的异步库的工作方式。
根据PEP525,asyncio
做了一些名为sys.set_asyncgen_hooks()
. trio
也这样做。我相信这就是异步生成器在它们下不能像我预期的那样工作的原因。这是可以理解的,因为它对于 finally 块包含await
.
所以我的问题是:
如果您使用的是 CPython,并且您使用的异步库没有执行上述操作,那么await
在没有引用它的情况下,finally 块中没有的异步生成器将立即关闭?
归档时间: |
|
查看次数: |
174 次 |
最近记录: |