假设我们有一个虚函数:
async def foo(arg):
result = await some_remote_call(arg)
return result.upper()
Run Code Online (Sandbox Code Playgroud)
有什么区别:
coros = []
for i in range(5):
coros.append(foo(i))
loop = get_event_loop()
loop.run_until_complete(wait(coros))
Run Code Online (Sandbox Code Playgroud)
和:
from asyncio import ensure_future
futures = []
for i in range(5):
futures.append(ensure_future(foo(i)))
loop = get_event_loop()
loop.run_until_complete(wait(futures))
Run Code Online (Sandbox Code Playgroud)
注意:该示例返回结果,但这不是问题的焦点.当返回值很重要时,请使用gather()而不是wait().
无论回报价值如何,我都在寻求清晰度ensure_future().wait(coros)并且wait(futures)都运行协同程序,所以何时以及为什么要将协程包装进去ensure_future?
基本上,使用Python 3.5运行一堆非阻塞操作的正确方法(tm)是async什么?
如果我想批量通话,如果需要额外的积分?例如,我需要调用some_remote_call(...)1000次,但我不想粉碎Web服务器/数据库/等1000个同时连接.这对于线程或进程池是可行的,但有没有办法做到这一点asyncio?
Guido van Rossum在2014年关于Tulip/Asyncio的演讲中展示了幻灯片:
任务与协同程序
相比:
- res =来自some_coroutine的收益率(...)
- res =来自任务的产量(some_coroutine(...))
任务可以在不等待的情况下取得进展
- 作为日志,你等待别的东西
- 即产量
我完全忽略了这一点.
从我的观点来看,两个结构都是相同的:
如果是裸协程 - 它会被调度,所以无论如何都会创建任务,因为调度程序与Tasks一起运行,然后协程调用程序协同程序被暂停,直到被调用者完成,然后可以自由继续执行.
如果Task- 完全相同 - 新任务被调度,调用者协程等待完成.
在这两种情况下执行代码的方式与开发人员在实践中应考虑的影响有何不同?
ps
非常感谢与权威来源(GvR,PEP,docs,核心开发者笔记)的链接.