我有一种情况想从异步 for 循环中中断。我设法将问题减少到下面的应用程序。我希望在从 main 中的循环中断时进入上下文管理器的“最后”部分。也就是说,预期的结果是
try
456
finally
done
但我得到的是
try
456
done
finally
然后在应用程序关闭时出现异常。
这是代码
import asyncio
from contextlib import asynccontextmanager
@asynccontextmanager
async def receiving():
try:
print('try')
yield 123
finally:
print('finally')
async def request_all():
async with receiving():
yield 456
async def main():
async for r in request_all():
print(r)
break
print('done')
asyncio.run(main())
我发现 this 错误报告看起来很相似,但据我所知,它已在 3.8 之前得到解决。我在 3.8.2 和 3.9.6 上测试了我的问题
最佳答案
我可以看出这种行为是多么令人困惑,但我不认为这是一个错误。如果你用 break
绕过异步迭代器的耗尽,你永远不会在 request_all
中留下 async with
,所以 finally
code>-block 在事件循环完成之前不会被执行。这样做的好处是您可以在稍后耗尽发电机。
如果您确定不再需要您的生成器,您可以关闭 async_generator 而不是 break
ing 以获得预期的行为:
import asyncio
from contextlib import asynccontextmanager
@asynccontextmanager
async def receiving():
try:
print('try')
yield 123
finally:
print('finally')
async def request_all():
async with receiving():
yield 456
async def main():
gen = request_all()
async for r in gen:
print(r)
await gen.aclose() #instead of break
print('done')
asyncio.run(main())
关于python - 从 Python 异步中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69836366/