python async,如何在Python中使用`async for`?

I mean what do I get from using async for. Here is the code I write with async for, AIter(10) could be replaced with get_range().

But the code runs like sync not 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())

The result I excepted should be :

start 1

start 2

start 3

...

end 1

end 2

...

finally 1

finally 2

...

However, the real result is:

start 0

end 0

finally 0

start 1

end 1

finally 1

start 2

end 2

I know I could get the excepted result by using asyncio.gather or asyncio.wait.

But it is hard for me to understand what I got by use async for here instead of simple for.

What is the right way to use async for if I want to loop over several Feature object and use them as soon as one is finished. For example:

async for f in feature_objects:

data = await f

with open("file", "w") as fi:

fi.write()

解决方案But it is hard for me to understand what I got by use async for here instead of simple for.

The underlying misunderstanding is expecting async for to automatically parallelize the iteration. It doesn't do that, it simply allows sequential iteration over an async source. For example, you can use async for to iterate over lines coming from a TCP stream, messages from a websocket, or database records from an async DB driver.

You could do none of the above with an ordinary for, at least not without blocking the event loop, because for calls __next__ as a blocking function and doesn't await its result. You cannot compensate by manually awaiting each element because for expects __next__ to signal the end of iteration by raising an exception - and if __next__ is a coroutine, the exception won't be visible before awaiting it. This is why async for was introduced, not just in Python, but also in other languages with async/await and generalized for.

If you want to run the iterations in parallel, you need to start them as parallel coroutines and use asyncio.as_completed or equivalent to retrieve their results as they come:

async def x(i):

print(f"start {i}")

await asyncio.sleep(1)

print(f"end {i}")

return i

for f in asyncio.as_completed([x(i) for i in range(10)]):

result = await f

# ... do something with the result ...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值