Python asyncio对等待和任务感到困惑

Python asyncio对等待和任务感到困惑,python,python-asyncio,Python,Python Asyncio,在此处填写新文档,阅读以下示例: import asyncio import time 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(

在此处填写新文档,阅读以下示例:

import asyncio
import time

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')}")

asyncio.run(main())
我最初对wait的理解是,它阻止当前函数的执行,并等待异步函数返回

但是在这种情况下,两个协同程序都是并发执行的,这不符合我对
wait
的理解。有人能解释一下吗


进一步调查,通过在
之后添加额外的
打印
,在我看来,直到
等待
发生,协同程序才开始

import asyncio
import time

async def say_after(delay, what):
    print('Received {}'.format(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')}")

asyncio.run(main())
印刷品

started at 13:41:23
Received hello
Received world
hello
world
finished at 13:41:25
started at 10:42:10
Received hello
Received world
hello
world
task 2 finished
task 1 finished
finished at 10:42:20

你对等待的理解是正确的。它会暂停主函数的执行

关键是
asyncio.create_task()
创建一个任务并安排它

因此,
say_after
函数在此处开始运行:

task1 = asyncio.create_task(
        say_after(1, 'hello'))

    task2 = asyncio.create_task(
        say_after(2, 'world'))
而不是在你等待的时候


请参见此处:

当您在任务(或未来)对象中封装协同路由时,协同路由已准备就绪,因此当事件循环在第一次等待时开始运行时,task1和task2都在运行。

为了让事情变得更清楚,要执行协同程序,您需要两件事:
1) 在未来对象(任务)中加入的使其可等待的协同程序
2) 正在运行的事件循环

在您的示例中,执行过程如下:
1-创建任务1
2-创建任务2
3-等待任务1
4-等待task1的睡眠
5-等待task2的睡眠

现在task1和task2都处于睡眠状态,因此,假设task1是第一个完成的任务(请稍后睡眠)

6-任务1的打印
7-等待任务2
8-任务2的打印

现在循环结束了

正如您所说,当您得到一个等待时,执行停止,但让我说,它仅在当前“执行流”中停止,当您创建一个未来(任务)时,您创建另一个执行流,而等待只是切换到当前执行流。 最后一种解释在术语上并不完全正确,但有助于使其更清楚

我希望我是清楚的。
注:对不起,我的英语不好。

好的@tsuyoku和@Fanto的答案都是正确的,这个答案只是为了补充现有的答案,对我来说,最重要的一点是我不能理解的是执行开始于

创建任务()

印刷品

started at 13:41:23
Received hello
Received world
hello
world
finished at 13:41:25
started at 10:42:10
Received hello
Received world
hello
world
task 2 finished
task 1 finished
finished at 10:42:20

最初的误解是,运行任务需要一些时间,而我问题中最初的打印输出误导了我,使我认为任务在
wait
语句之前不会运行。

是的,我知道这就是任务,但如果是任务,
wait
会改变它的行为,这似乎很奇怪。你能澄清一下你认为它的行为是如何改变的吗
wait
使main等待异步函数
say_after
返回。协同程序在
wait task1
之前不会启动,因此它不像
线程。join
在创建任务时从
asyncio.创建_任务(在(1,'hello'))之后说_)
。尝试在不使用
wait
行的情况下运行代码,您会发现程序仍然打印出
hello world
。请查看我的最新更新,它在打印
启动时间戳后打印
收到的字
创建任务()
不会立即启动协同程序,它只在
等待任务1
之前启动,但我的理解是
唤醒任务1
应该阻止执行
等待任务2
,直到
任务1
完成。我认为您的理解是正确的,但只是从调用等待的函数的角度来看,从全局的角度来看,wait只是将执行切换到另一个任务,这就是为什么协同程序的多任务处理是协作的,而不是抢占式的。我只是无法让
wait task1
块开始执行
wait task2
,如果在当前函数上下文中未执行
wait task2
,那么
task2
如何与
task1
同时运行。