【问题标题】:Why is awaiting on task faster than awaiting on coroutine?为什么等待任务比等待协程更快?
【发布时间】:2020-01-02 02:05:10
【问题描述】:

为什么等待任务比等待协程更快?

我正在查看文档https://docs.python.org/3/library/asyncio-task.html

这个例子特别:

等待任务


async def say_after(delay, what):
    await asyncio.sleep(delay)
    print(what)


async def main():
    task1 = asyncio.create_task(
        say_after(1, 'hello'))

    task2 = asyncio.create_task(
        say_after(2, 'world'))

    print(f"started at {time.strftime('%X')}")

    # Wait until both tasks are completed (should take
    # around 2 seconds.)
    await task1
    await task2

    print(f"finished at {time.strftime('%X')}")

与协程

import asyncio
import time

async def say_after(delay, what):
    await asyncio.sleep(delay)
    print(what)

async def main():
    print(f"started at {time.strftime('%X')}")

    await say_after(1, 'hello')
    await say_after(2, 'world')

    print(f"finished at {time.strftime('%X')}")

asyncio.run(main())

【问题讨论】:

    标签: python-3.x task coroutine


    【解决方案1】:

    等待一个任务并不比等待一个协程快。 当您使用 asyncio.create_task 时,您正在为给定函数创建一个新任务,因此 python 为该函数创建一个任务并转到下一行。 当您正在等待一项任务时,您只是在等待它完成。

    import asyncio
    
    async def task(delay, id):
        print(f'task with the id of {id} created (delay: {delay})')
        await asyncio.sleep(delay) # some calculation the takes time
        print(f'task {id} finished the heavy calculation')
    
    async def main(loop):
        task1 = asyncio.create_task(task(3, 1))
        task2 = asyncio.create_task(task(5, 2))
        task3 = asyncio.create_task(task(1, 3))
    
    
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(loop))
    loop.run_forever()
    

    正如您在这段代码中看到的,我们没有等待任务完成并且 每个人都花时间完成。

    说明:

    • task1 - 创建一个立即执行函数的任务
    • task2 - 创建任务 1 后创建任务(创建未完成,同时 task1 功能仍在运行)
    • task3 - 在所有任务创建后创建(同时 task1/2 的函数正在运行)
    • main函数执行完毕并关闭
    • loop.run_forver() 不让程序结束
    • 任务的输出

    如果您删除loop.run_forever(),程序将在不等待任务完成的情况下关闭,这就是为什么有时您需要await 一个任务,因为您需要该值。

    例如(相同代码更改主函数):

    async def main(loop):
        task1 = asyncio.create_task(task(3, 1))
        task2 = asyncio.create_task(task(5, 2))
        task3 = asyncio.create_task(task(1, 3))
    
        x = await task1
    
    
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(loop))
    

    这只会等待task1完成并退出代码(没有loop.run_forever())。

    【讨论】:

      最近更新 更多