繁体   English   中英

Asyncio 执行流程问题

[英]Asyncio execution flow issue

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

我所做的是,在outer函数中,我创建了异步任务并将其存储在数组tasks 在等待这些任务之前,我写了一个应该在每次迭代中运行的打印语句print("outer") 在任务中,我在inner函数中编写了另一个打印语句print("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 的正确执行流程是什么? 提前致谢。

async def outer(loop)

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

如果您在innerouter添加更多内容,则可以更好地显示此过程:

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 上看过显示该过程的视频,不幸的是我无法快速找到我想要链接的视频。

loop.create_task(inner())立即将所有 5 个inner任务排队await task运行,而不是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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM