Ana*_*and 9 python async-await python-asyncio
Python Language Reference 规定object.__await__如下:
object.__await__(self)必须返回一个迭代器。应该用于实现可等待的对象。例如,
asyncio.Future实现此方法以与 await 表达式兼容。
就是这样。我觉得这个规范很模糊,也不是很具体(讽刺的是)。好的,它应该返回一个迭代器,但它可以是一个任意的迭代器吗?显然不是:
import asyncio
class Spam:
def __await__(self):
yield from range(10)
async def main():
await Spam()
asyncio.run(main())
Run Code Online (Sandbox Code Playgroud)
RuntimeError: Task got bad yield: 0
Run Code Online (Sandbox Code Playgroud)
我假设asyncio事件循环期望迭代器产生特定类型的对象。那么它究竟应该产生什么?(为什么没有记录在案?)
编辑:据我所知,这在任何地方都没有记录。但我一直在调查我自己,我觉得关键是了解哪些对象asyncio预计其协同程序产生在于task_step_impl中_asynciomodule.c。
更新:我做了一个PR与此澄清的目的CPython的库:“明确的模糊规范object.__await__”。目前正在审核中。
该语言不关心您返回哪个迭代器。该错误来自asyncio库,它对迭代器必须生成的值类型有特定的想法。Asyncio 需要__await__生成 asyncio 期货(包括它们的子类型,例如任务)或None. 其他库,如 curio 和 trio,将期待不同类型的值。异步库基本上没有记录他们的期望,__await__因为他们认为这是一个实现细节。
就 asyncio 而言,除了协程之外,您还应该使用更高级别的构造,例如期货和任务,并等待它们。很少需要__await__手动实现,即便如此,您也应该使用它来委托另一个可等待的信号。编写一个__await__创建并产生它自己的新挂起值的 ,需要它与事件循环耦合并了解其内部结构。
您可以将其__await__视为编写类似于 asyncio 的库的工具。如果你是这样一个库的作者,当前的规范就足够了,因为你可以从迭代器中产生任何你喜欢的东西,只有你的事件循环中的代码会观察产生的值。如果您不在那个位置,您可能不需要实施__await__.