python - 开始处理异步任务,同时将它们添加到事件循环中
问题描述
asyncio 的一个常见模式,就像这里展示的那样,是将一组协程添加到列表中,然后添加asyncio.gather
它们。
例如:
async def some_task(i):
# Do something asynchronously with i
tasks = [some_task(i) for i in range(100)]
loop.run_until_complete(asyncio.gather(**tasks))
在这里,这段代码的执行顺序是在我们构建列表时没有任何任务在运行。我们将任务 1 添加到列表中,然后添加任务 2,等等,然后我们将任务 1-100 添加到事件循环中。
但是,我希望任务创建本身成为事件循环的一部分。我希望任务 1 在创建时立即安排,然后当任务在另一个线程上等待某些东西时,返回任务创建并创建任务 2 并将其添加到事件循环中。
我相信这会给我的异步代码带来更好的并发性。这可能吗?
例如,我的第一个想法是将任务创建放入协程中,并在创建任务时安排任务:
async def some_task(i):
# Do something asynchronously with i
async def generate_tasks(loop):
tasks = []
for i in range(100):
task = loop.create_task(some_task(i))
tasks.append(loop)
await asyncio.gather(**tasks)
loop.run_until_complete(generate_tasks())
但是,因为 my generate_tasks
never uses await
,所以执行永远不会传递回事件循环,所以generate_tasks
will run before的全部内容根本不会运行some_task()
。
但是,如果我await
在创建每个任务时,它会等待每个任务完成,然后再继续下一个任务,根本不给我并发!
async def generate_tasks(loop):
tasks = []
for i in range(100):
await some_task(i)
loop.run_until_complete(generate_tasks())
解决方案
但是,因为我
generate_tasks
从不使用await
,所以永远不会将执行传递回事件循环
您可以使用await asyncio.sleep(0)
来强制让步到里面的事件循环for
。但这不太可能产生影响,创建任务/协程对确实有效。
在优化它之前,测量(用一些简单的东西,time.time
好像需要)执行[some_task(i) for i in range(100)]
列表理解需要多少时间。然后考虑分散该时间(可能由于增加调度开销而使完成时间更长)是否会对您的应用程序产生任何影响。结果可能会让你大吃一惊。
推荐阅读
- servlets - JavaEE servlet setAttribute 有什么用
- sql - 从同一个表中复制行并使用不同的 ID 列和另一列进行更新
- arrays - 用户在一行中输入命令和 int 以及如何验证他们是否放置了正确的命令
- spring - 为什么我的 JdbcTokenStore 存储序列化 Java 对象?
- git - 如何使用 Git 进行部署 - 远程存储库未被识别为 Git 库
- java - cucumber-jvm 版本 3 替代设计模式用于简单表映射
手术 - javascript - 打开新标签并使用 javascript 更改标题
- ios - React Native 和字体变体
- django - Django如何使用webhook和发布数据?
- python - 在单轴上绘制值,但也在标签上(一维散点图)