阅读
异步文档
,我意识到我不理解一个非常基本和基本的方面:直接等待协程和当它被包装在任务中时等待相同的协程之间的区别。
在文档示例中,对
协程在没有等待的情况下按顺序运行
,并且当包装在
..。所以我明白这基本上就是不同之处,而且这是一个相当重要的区别。
然而,令我困惑的是,在示例代码中,我到处都在阅读(例如,展示如何使用
),有许多地方等待(用户定义的)协程(通常在其他一些用户定义的协程的中间)而不被包装在任务中,我想知道为什么会这样。确定何时应该在任务中包装协程的标准是什么?
发布于 2019-09-17 14:36:29
确定何时应该在任务中包装协程的标准是什么?
您应该使用
任务
当你想让你的协程有效地运行时
在后台
..。您已经看到的代码直接等待协程,因为它需要它们按顺序运行。例如,假设一个HTTP客户端发送请求并等待响应:
# these two don't make too much sense in parallel
await session.send_request(req)
resp = await session.read_response()在某些情况下,当你
想要
并行运行的操作。在这种情况下
是合适的工具,因为它将执行协程的责任交给了事件循环。这允许您启动多个协程,并在它们执行时闲置,通常等待它们的部分或全部完成:
dl1 = asyncio.create_task(session.get(url1))
dl2 = asyncio.create_task(session.get(url2))
# run them in parallel and wait for both to finish
resp1 = await dl1
resp2 = await dl2
# or, shorter:
resp1, resp2 = asyncio.gather(session.get(url1), session.get(url2))如上所示,也可以等待任务。就像等待协程一样,这将阻塞当前的协程,直到任务驱动的协程完成。与线程类似,等待任务大致等同于-ing()join()线程(除非返回返回值)。另一个例子:
queue = asyncio.Queue()
# read output from process in an infinite loop and
# put it in a queue
async def process_output(cmd, queue, identifier):
proc = await asyncio.create_subprocess_shell(cmd)
while True:
line = await proc.readline()
await queue.put((identifier, line))
# create multiple workers that run in parallel and pour
# data from multiple sources into the same queue
asyncio.create_task(process_output("top -b", queue, "top")
asyncio.create_task(process_output("vmstat 1", queue, "vmstat")
while True:
identifier, output = await queue.get()
if identifier == 'top':
# ...总而言之,如果您需要协程的结果才能继续,您应该等待它,而不创建任务,即:
# this is ok
resp = await session.read_response()
# unnecessary - it has the same effect, but it's
# less efficient
resp = await asyncio.create_task(session.read_reponse())为了继续线程的类比,创建一个立即等待的任务就像运行
而不是仅仅
-低效和冗余。
https://stackoverflow.com/questions/57966935
复制相似问题