python-3.x 为什么等待任务比等待协程快?

t2a7ltrp  于 2023-05-02  发布在  Python
关注(0)|答案(2)|浏览(187)

为什么等待任务比等待协程快?
我在看文档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())
bsxbgnwa

bsxbgnwa1#

等待一个任务并不比等待一个协程快。当你使用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-在task 1创建后创建一个任务(创建未完成,同时task 1函数仍在运行)
  • task3-在所有任务创建后创建(同时运行task 1/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))

这将只等待task 1完成并退出代码(没有loop.run_forever())。

lf3rwulv

lf3rwulv2#

等待协程等待执行完成。等待一个任务。不同之处在于,当创建一个任务时,它会在创建时被调度并尽快执行(通常是立即执行),独立于它所在的协程。当一个任务的执行结果是想要的时候,它有时已经完成了。这就是为什么当运行超过1个协程时它会更快。
然而,协程尚未被调度或执行。只有在等待的时候才会执行。因此,它是同步工作的。
这是如何工作的一些例子。..
等待协程的示例:

import asyncio
import time

async def say_after(delay, what):
    print(f'Task executing 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())

返回结果:

started at 21:23:00
Task executing say_after(1, hello)
hello
Task executing say_after(2, world)
world
finished at 21:23:03

等待任务示例:

import asyncio
import time

async def say_after(delay, what):
    print(f'Task executing 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')}")

    await task1
    await task2

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

asyncio.run(main())

返回结果:

started at 21:25:54
Task executing say_after(1, hello)
Task executing say_after(2, world)
hello
world
finished at 21:25:56

相关问题