英文:
Process an Asynchronous Iterator in background
问题
I trying to process an asynchronous iterator in background.
I can process in the main function:
target = ...
async def main():
async for item in target.listen():
print(item) # works fine
print('done') # never arrives, because loop iterates forever
asyncio.run(main())
But doing it this way, the code is blocking.
So I try process the iterator in other function with create_task, but the loop never iterates.
target = ...
async def process():
async for item in target.listen():
print(item) # never print
async def main():
asyncio.create_task(process())
print('done') # works
asyncio.run(main())
Is it possible to process an asynchronous iterator in background? How?
英文:
I trying to process an asynchronous iterator in background.
I can process in the main function:
target = ...
async def main():
async for item in target.listen():
print(item) # works fine
print('done') # never arrives, because loop iterates forever
asyncio.run(main())
But doing it this way, the code is blocking.
So I try process the iterator in other function with create_task, but the loop never iterates.
target = ...
async def process():
async for item in target.listen():
print(item) # never print
async def main():
asyncio.create_task(process())
print('done') # works
asyncio.run(main())
Is it possible to process an asynchronous iterator in background? How?
答案1
得分: 1
如果您调用create_task()
然后立即退出 - 这是您在代码中正在做的事情 - 那么任务当然不会运行。只有在前台执行某事,才能在“后台”运行某事,而您没有这样做。
即使您的main
函数不立即退出,您的后台任务仍不会运行。Asyncio提供并发执行,但不提供并行执行 - 除非当前任务通过调用await
来让出控制权,否则其他任务不会执行。
这是一个工作示例;我已经用一个简单的单词列表替换了您的target
变量,以便我们可以迭代:
import asyncio
target = "one two three four five six".split()
async def process():
for item in target:
print(item) # 不会立即打印
await asyncio.sleep(0.3)
async def main():
task = asyncio.create_task(process())
while not task.done():
print("在等待时做一些事情")
await asyncio.sleep(1)
print("完成")
asyncio.run(main())
运行上述代码会产生以下输出:
在等待时做一些事情
one
two
three
four
在等待时做一些事情
five
six
完成
与我在此示例中所做的检查task.done()
不同,您在实践中更有可能使用其中的一个等待原语或 asyncio.gather
来等待后台任务的完成。
英文:
If you call create_task()
and then immediately exit -- which is what you're doing in your code -- then of course the task never runs. You can only run something "in the background" if you're doing something in the foreground, and you're not.
Even if your main
function wasn't exiting immediately, your background task still wouldn't run. Asyncio provides concurrent execution, but not parallel execution -- other tasks won't execute unless the current task yields control by calling await
.
Here's a working example; I've replaced your target
variable with a simple list of words just so we have something over which to iterate:
import asyncio
target = "one two three four five six".split()
async def process():
for item in target:
print(item) # never print
await asyncio.sleep(0.3)
async def main():
task = asyncio.create_task(process())
while not task.done():
print("doing something while waiting")
await asyncio.sleep(1)
print("done")
asyncio.run(main())
Running the above code produces:
doing something while waiting
one
two
three
four
doing something while waiting
five
six
done
Rather than checking for task.done()
as I've done in this example, you would in practice be more likely to use one of the waiting primitives or asyncio.gather
to wait for the completion of background tasks.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论