我的意思是我从使用async for
得到什么。这是我用async for
编写的代码,AIter(10)
可以替换为get_range()
。在
但是代码的运行方式类似于sync而不是async。在
import asyncio
async def get_range():
for i in range(10):
print(f"start {i}")
await asyncio.sleep(1)
print(f"end {i}")
yield i
class AIter:
def __init__(self, N):
self.i = 0
self.N = N
def __aiter__(self):
return self
async def __anext__(self):
i = self.i
print(f"start {i}")
await asyncio.sleep(1)
print(f"end {i}")
if i >= self.N:
raise StopAsyncIteration
self.i += 1
return i
async def main():
async for p in AIter(10):
print(f"finally {p}")
if __name__ == "__main__":
asyncio.run(main())
我排除的结果应该是:
^{pr2}$然而,真正的结果是:
start 0
end 0
finally 0
start 1
end 1
finally 1
start 2
end 2
我知道我可以通过使用asyncio.gather
或asyncio.wait
得到例外结果。在
但是我很难理解在这里用async for
而不是简单的for
得到了什么。在
如果我想在多个Feature
对象上循环并在一个对象完成后立即使用它们,那么使用async for
的正确方法是什么。例如:
async for f in feature_objects:
data = await f
with open("file", "w") as fi:
fi.write()
潜在的误解是您似乎期望^{} 自动地将迭代并行化。它不这样做,它只是允许在异步源上进行顺序迭代。例如,可以使用
async for
来迭代来自TCP流的行、来自websocket的消息或来自异步DB驱动程序的数据库记录。在使用普通的} 作为一个阻塞函数调用,而不等待其结果。您不能通过手动等待每个元素来进行补偿,因为}。在
for
就不能执行上述任何操作,至少在不阻塞事件循环的情况下是这样,因为for
将^{for
希望__next__
通过引发异常来发出迭代结束的信号,并且如果__next__
是一个协程,则在等待异常之前,异常将不可见。这就是为什么async for
不仅在Python中被引入,而且在otherlanguages中也引入了async/await和{如果您想并行运行迭代,您需要将它们作为并行协程启动,并使用^{} 或等效方法来检索它们的结果:
相关问题 更多 >
编程相关推荐