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
同时运行。