await Coroutine 和 await Task 的区别
Posted
技术标签:
【中文标题】await Coroutine 和 await Task 的区别【英文标题】:Difference between await Coroutine and await Task 【发布时间】:2021-11-13 21:59:56 【问题描述】:在 FastAPI 上,我有一个端点调用下面的 get_1
或 get_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
的确切作用以及task
与future
的不同之处,我建议从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 executed
在await 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 的区别的主要内容,如果未能解决你的问题,请参考以下文章
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