何时在异步执行`create_task()`上的任务? [英] When is the task at `create_task()` executed in asyncio?

查看:66
本文介绍了何时在异步执行`create_task()`上的任务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在以下代码中:

 导入异步异步def task_func():打印('在task_func')返回结果"异步def main(循环):打印(正在创建任务")任务= loop.create_task(task_func())print('正在等待{!r}'.format(task))等待asyncio.sleep(2)return_value =等待任务print('任务完成{!r}'.format(task))print('返回值:{!r}'.format(return_value))event_loop = asyncio.new_event_loop()尝试:event_loop.run_until_complete(main(event_loop))最后:event_loop.close() 

执行代码时,结果如下:

 创建任务等待<任务待定coro =< task_func()在< ipython-input-29-797f29858344>:>>上运行".在task_func中任务已完成`<任务已完成coro =< task_func()完成,在< ipython-input-29-797f29858344>:1>中定义result ='结果'>`返回值:结果" 

但是我不明白何时执行在 loop.create_task(task_func())中设置的代码.具体来说,我假设将任务添加到事件循环时,该任务很快就会执行,因此我认为在等待< Task ... 之前先打印task_func 中的.

然后我发现它总是在等待< Task ... 之后执行,因此我添加了 await asyncio.sleep(2),但仅发现2秒结束之前已打印task_func 中的.

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

所以现在我被搞糊涂了.将任务添加到 loop.create_task()中的事件循环后,何时执行任务?

解决方案

具体来说,我假设将任务添加到事件循环时,该任务很快就会执行,因此我认为在等待< Task ....之前打印出task_func 中的./code>

即将执行"并不意味着立即执行.相反,您可以将其视为执行了获得的第一个机会",我们是事件循环.由于 print 立即跟随对 create_task 的调用,因此事件循环还没有机会运行.为了使事件循环有运行的机会,您必须返回到事件循环,方法是从当前协程返回,或者等待阻塞的事件.

当您 await 阻塞的协程(例如 asyncio.sleep())时,协程将暂时挂起自身并放弃对事件循环的控制.事件循环将查看睡眠结束之前还有什么要做,并在其运行队列中找到使用 create_task 安排的任务.这就是为什么当 main 协程等待睡眠时执行 task_func task_func_2 的原因-但在此之前,并且无论您是否等待特别是它们或其他阻塞的东西.

等待一个协程,例如 task_func 意味着在那儿然后在那里请求它的结果,并准备等待它.(这种等待会自动将执行推迟到事件循环,从而允许其他协程取得进展.)尽管实现有所不同,但是 await 在概念上类似于 join 线程./p>

In the following code:

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()

When I execute the code, the result is the following:

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'

But I don't understand when the code you set at loop.create_task(task_func()) is executed. Specifically, I assumed when you add a task to the event loop, it is executed soon, so I thought in task_func is printed before waiting for <Task....

Then I found it is always executed after the waiting for <Task..., so I added await asyncio.sleep(2), but only found that the in task_func is printed before the finish of 2 seconds.

I also added task_func_2() which is practically the same as task_func() and create its task below task = loop.create_task(task_func()) but do NOT add return_value_2 = await task2, so the await does not execute the task (otherwise the task_func_2() is never executed).

So now I got confuesed. When is the task is executed after it is added to the event loop in loop.create_task()?

解决方案

Specifically, I assumed when you add a task to the event loop, it is executed soon, so I thought in task_func is printed before waiting for <Task....

"Executed soon" doesn't mean executed right away. Instead, you can think of it as "executed the first chance we get," we being the event loop. Since print immediately follows the call to create_task, at that point the event loop hasn't yet had a chance to run at all. To give event loop a chance to run, you must return to the event loop, either by returning from the current coroutine, or by awaiting something that blocks.

When you await a blocking coroutine such as asyncio.sleep(), the coroutine will temporarily suspend itself and relinquish control to the event loop. The event loop will look at what else there is to do before the sleep elapses and will find the tasks scheduled using create_task in its run queue. This is why task_func and task_func_2 are executed when the main coroutine awaits the sleep - but not before that, and regardless of whether you await them in particular or something else that blocks.

awaiting a coroutine such as task_func means requesting its result then and there, and being prepared to wait for it. (Such wait automatically defers execution to the event loop, allowing other coroutines to make progress.) Although the implementation differs, an await is conceptually similar to joining a thread.

这篇关于何时在异步执行`create_task()`上的任务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆