Asyncio执行流程问题

问题描述 投票:0回答:2

我对 python 中的 asyncio 有点陌生。我试图运行这个简单的代码,但我不知道为什么我会得到这个意外的输出。

我所做的是,在

outer
函数中,我创建了异步任务并将其存储在数组
tasks
中。在等待这些任务之前,我编写了一条打印语句
print("outer")
,该语句应该在每次迭代中运行。在任务中,我在
print("inner")
函数中编写了另一个打印语句
inner
。但我如何得到一些意想不到的输出。

这是代码 -

import asyncio


def main():
    loop = asyncio.get_event_loop()
    loop.run_until_complete(outer(loop))
    loop.close()


async def outer(loop):
    tasks = []
    for i in range(0, 5):
        tasks.append(loop.create_task(inner()))

    for task in tasks:
        print("outer")
        await task


async def inner():
    print("inner")
    await asyncio.sleep(0.5)

if __name__ == '__main__':
    main()

这是输出 -

outer
inner
inner
inner
inner
inner
outer
outer
outer
outer

我的预期输出是 -

outer
inner
outer
inner
outer
inner
outer
inner
outer
inner

为什么所有的

inner
都在
outer
之前打印。 asyncio的正确执行流程是怎样的?预先感谢。

python asynchronous async-await python-asyncio
2个回答
3
投票

async def outer(loop)

for i in range(0, 5):
    tasks.append(loop.create_task(inner()))
  • 五个新的
    inner
    任务已创建、计划并开始运行。
  • 事件循环运行计划任务直到完成。

如果您在

inner
outer
上添加一点内容,它会更好地显示此过程:

async def outer(loop):
    tasks = []
    for i in range(0, 5):
        tasks.append(loop.create_task(inner(i)))
    await asyncio.sleep(3)
    for task in tasks:
        print('outer')
        await task

async def inner(n):
    print(f"inner {n} start")
    await asyncio.sleep(0.5)
    print(f'inner {n} end')
  • outer
    睡觉时

    • 第一个任务运行到它的await语句
    • 事件循环暂停第一个任务的执行
    • 事件循环运行下一个计划任务直到其await语句
    • 这一直持续到每个任务有机会运行到其await语句为止,然后事件循环开始四处查看是否有任何任务已完成等待它们正在等待的任何任务 - 如果完成,它会让它们运行更多。
    • 这一直持续到所有任务完成
  • 您可以看到五个任务在第二个 for 循环开始之前就执行并完成了。

  • 在第二个 for 循环中,每个任务都已完成,因此

    await task
    无需等待,
    outer
    会连续打印五次。

我对控制一切的事件循环有点模糊 - 我还没有找到任何明确的文档 - 可能在

create_task
文档中提到:
Wrap the coro coroutine into a Task and schedule its execution.
当您创建任务时,它会被安排。我在 pyvideo.org 上看过显示该过程的视频,不幸的是我无法快速找到我想要链接的视频。


1
投票

loop.create_task(inner())
立即将所有 5 个
inner
任务排队等待运行,而不是
await task
await task
会暂停
outer
,直到第一个任务完全 完成,即至少 0.5 秒。在此期间,所有
inner
任务都已运行一次
await
,包括它们的
print


async def outer(loop):
    tasks = []
    for i in range(0, 5):
        # queues task immediately
        tasks.append(loop.create_task(inner()))

    for task in tasks:
        print("outer")
        # suspends for at least 0.5 seconds
        await task


async def inner():
    # runs immediately
    print("inner")
    await asyncio.sleep(0.5)
© www.soinside.com 2019 - 2024. All rights reserved.