在asyncio中执行`create_task()`的任务是什么时候?

时间:2018-05-03 13:33:14

标签: python asynchronous python-asyncio

在以下代码中:

import asyncio

async def task_func():
    print('in task_func')
    return 'the result'


async def main(loop):
    print('creating task')
    task = loop.create_task(task_func())
    print('waiting for {!r}'.format(task))
    await asyncio.sleep(2)
    return_value = await task
    print('task completed {!r}'.format(task))
    print('return value: {!r}'.format(return_value))


event_loop = asyncio.new_event_loop()
try:
    event_loop.run_until_complete(main(event_loop))
finally:
    event_loop.close()

执行代码时,结果如下:

creating task
waiting for `<Task pending coro=<task_func() running at <ipython-input-29-797f29858344>:1>>`
in task_func
task completed `<Task finished coro=<task_func() done, defined at <ipython-input-29-797f29858344>:1> result='the result'>`
return value: 'the result'

但我不明白您在loop.create_task(task_func())设置的代码何时执行。具体来说,我假设当您向事件循环添加任务时,它很快就会执行,因此我认为in task_func之前会打印waiting for <Task...

然后我发现始终waiting for <Task...之后执行,所以我添加了await asyncio.sleep(2),但只发现in task_func在完成之前打印2秒。

我还添加了task_func_2(),它与task_func()几乎相同,并在task = loop.create_task(task_func())下面创建了任务但不添加return_value_2 = await task2,因此await会不执行任务(否则永远不会执行task_func_2())。

所以现在我被困惑了。何时将任务添加到loop.create_task()

中的事件循环后执行

1 个答案:

答案 0 :(得分:5)

  

具体来说,我假设你在事件循环中添加一个任务时很快就会执行,所以我认为在in task_func之前打印waiting for <Task....

“尽快执行”并不意味着马上执行。相反,你可以把它想象成“我们得到的第一次机会”,我们是事件循环。由于print紧跟在create_task的调用之后,此时事件循环还没有机会运行。要为事件循环提供运行机会,必须返回事件循环,方法是从当前协程返回,或等待阻塞的东西。

当您await阻塞协程如asyncio.sleep()时,协程将暂时暂停并放弃对事件循环的控制。事件循环将查看在睡眠过去之前还要做的其他事情,并将在其运行队列中找到使用create_task计划的任务。这就是为什么task_functask_func_2main协程等待睡眠时执行的原因 - 而不是在此之前执行,而不管您是否特别await或其他块。

await诸如task_func之类的协程意味着在那时请求其结果,并准备等待它。 (这种等待会自动将执行推迟到事件循环,允许其他协同程序取得进展。)虽然实现方式不同,但await在概念上类似于join一个线程。