首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Python asyncio对等待和任务感到困惑

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

Stack Overflow用户
提问于 2019-05-23 05:19:52
回答 3查看 1.2K关注 0票数 1

在这里完成newb,阅读有关Asycnio Tasks的信息,其中包含以下示例:

代码语言:javascript
复制
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())

我最初对await的理解是,它会阻塞当前函数的执行,并等待异步函数返回。

但在这种情况下,两个协程都是并发执行的,这与我对await的理解不太相符。有没有人能解释一下?

进一步的调查,通过在say_after中添加额外的print,在我看来,协程在await发生之前是不会开始的……

代码语言:javascript
复制
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())

打印

代码语言:javascript
复制
started at 13:41:23
Received hello
Received world
hello
world
finished at 13:41:25
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-05-23 05:47:37

当您将协程封装在任务(或未来)对象中时,协程就可以工作了,因此当事件循环在第一个等待时开始运行时,task1和task2都在运行。

为了让它更清晰,为了执行协程,你需要做两件事:

1)封装在未来对象(任务)中的协程,以使其可等待

2)运行的事件循环

在您的示例中,执行过程如下所示:

1- create_task1

2- create_task2

3-等待task1

4-等待task1休眠

5-等待task2睡眠

现在task1和task2都在休眠,假设task1是第一个完成的(休眠一段时间)

6-打印task1

7-等待task2

8-打印task2

现在循环结束了

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

我希望我说得够清楚了。附言:对不起,我的英语不好。

票数 1
EN

Stack Overflow用户

发布于 2019-05-23 05:27:40

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

关键是asyncio.create_task()创建任务并对其进行调度。

因此,say_after函数从这里开始运行:

代码语言:javascript
复制
task1 = asyncio.create_task(
        say_after(1, 'hello'))

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

而不是在你等待的时候。

查看此处:https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task

票数 2
EN

Stack Overflow用户

发布于 2019-05-28 06:48:17

好的,@tsuyoku和@Fanto的答案都是正确的,这个答案只是对现有答案的补充,对我来说,我不能掌握的重要一点是在create_task()上开始执行

代码语言:javascript
复制
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')}")
    await asyncio.sleep(10)

    # Wait until both tasks are completed (should take
    # around 2 seconds.)
    await task2
    print('task 2 finished')
    await task1
    print('task 1 finished')

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

asyncio.run(main())

打印

代码语言:javascript
复制
started at 10:42:10
Received hello
Received world
hello
world
task 2 finished
task 1 finished
finished at 10:42:20

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56265166

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档