主要观点:在 Python 中实现的异步流抽象中,异步生成器的可预测清理存在显著问题,普通生成器也有类似问题但影响较小,未完全消耗生成器时会出现意外清理行为,可通过内联gen
调用或使用del
语句、close
方法或closing
上下文管理器来确保清理,异步生成器的清理管理更复杂,不同事件循环实现可能处理方式不同,显式清理代码在异步代码中尤其重要。
关键信息:
- 展示了普通生成器和异步生成器的清理示例及不同运行时环境下的结果,如 CPython 和
pypy
。 - 介绍了生成器的相关方法如
close
、send
、throw
等。 - 提及
contextlib
库中的closing
和aclosing
上下文管理器。
重要细节: - 普通生成器示例中,未完全消耗生成器会导致清理代码在函数退出时执行,内联
gen
调用或使用del
可改善情况。 - 异步生成器示例中,
await asyncio.sleep(0)
在asyncio.run
中用于启用“取消”,不同运行时环境下清理行为不同。 - 显式清理在异步代码中重要的原因,如不同事件循环实现和使用运行时上下文的清理代码。
结论:使用生成器(异步或非异步)时遵循可预测的清理习惯是良好实践,研究此问题让作者对异步生成器有了更好理解。
额外阅读:PEP 525 描述异步生成器及其实现,包括异步生成器钩子;PEP 533 提出同步和异步迭代器协议的扩展以支持for
循环中的确定性清理;contextlib
文档中提到async with aclosing(gen()) as generator:
习惯用法。
备注:1 提到工作时与语言模型的“流”相关以改善高延迟完成的用户体验;2 指出 CPython 利用引用计数和代垃圾收集器处理循环引用,pypy
使用自己的增量垃圾收集器且无引用计数。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。