await Coroutine 和 await Task 的区别

Posted

技术标签:

【中文标题】await Coroutine 和 await Task 的区别【英文标题】:Difference between await Coroutine and await Task 【发布时间】:2021-11-13 21:59:56 【问题描述】:

在 FastAPI 上,我有一个端点调用下面的 get_1get_2 协程函数。

get_1 使用 await redis.get(key)

get_2 使用await asyncio.ensure_future(redis.get(key))

这两个函数在功能和性能方面有什么区别吗?

#redis.py

import asyncio
import aioredis

async def get_1(key):
   redis = aioredis.from_url("redis://localhost")
   value = await redis.get(key)
   return value

async def get_2(key):
   redis = aioredis.from_url("redis://localhost")
   value = await asyncio.ensure_future(redis.get(key))
   return value

【问题讨论】:

我怀疑get_2() 是更旧的代码。随着 Python 的每个版本,异步框架变得更加简洁。 asyncio.ensure_future 是一个低级 API,应该不再需要在大多数代码中使用它。 我同意较新的 Python,get_2() 应该使用 asyncio.create_task。那我还是有同样的问题。 【参考方案1】:

首先,要了解await 的确切作用以及taskfuture 的不同之处,我建议从topic 开始,当然还有官方documentation。

至于你的问题,乍一看,await coro()await create_task(coro()) 这两个表达式做同样的事情。他们启动协程,等待它完成并返回结果。

但是有一些重要的区别:

await coro() 导致直接调用协程代码,而不会将执行路径返回到事件循环。此问题已在 topic 中进行了解释。 await create_task(coro()) 导致将协程包装在task 中,在事件循环中调度其执行,将执行路径返回到事件 循环然后等待结果。在这种情况下,在执行目标协程(作为任务调度)之前,可以执行其他已经调度的任务。 通常,await 不与create_task 一起使用,以允许衍生任务并行运行,但有时需要,下一段中的示例 await coro() 在当前变量context 中执行目标协程,await create_task(coro()) 在当前上下文副本中执行(更多详细信息请参见topic)。

根据上述情况,您很可能需要await coro(),而将第二个表达式用于更具体的情况。

【讨论】:

关于第二点:我认为await create_task(coro()) 创建一个任务并立即等待它,因此应该阻止执行与第一点可以。您的解释是指other already scheduled tasks can be executedawait create_task(coro()) 下。我想知道是否有任何参考来支持这第二点? 当然,摘自官方documentation:[Task is]一个future-like对象。 [...] 事件循环使用协作调度:事件循环一次运行一个任务。当 Task 等待 Future 完成时,事件循环运行其他 Tasks、回调或执行 IO 操作。 我想辩论。摘录解释了当一个任务的coro() 正在等待某些东西时,事件循环收回控制权并可以运行另一个任务的另一个coro()。它没有解释await create_task(coro()) 发生了什么,即当create_task (1) 和await (2) 一起发生时。您的第二点说,在 (1) 和 (2) 之间的 非常短的时间内,事件循环 可以 收回控制权以运行其他东西。我的怀疑是事件循环不能收回(1)和(2)之间的控制权,因为也许非常短的时间就像0?跨度> 关键是事件循环不会自行控制,任务会在他们认为合适的时候将其交出。特别是await task,肯定会把控制权交给事件循环,这里没有时间赛跑的地方。

以上是关于await Coroutine 和 await Task 的区别的主要内容,如果未能解决你的问题,请参考以下文章

六十五 async/await

Kotlin Coroutine,Android Async Task 和 Async await 的区别

C# 的 async/await 其实是stackless coroutine

RuntimeWarning: coroutine 'script' is never awaited content = str(content) if content is not None el

yortus/asyncawait,tj/co 这两个 nodejs 库有何区别

Awaitable