Python 异步中循环的并行化

Python 异步中循环的并行化,python,python-asyncio,Python,Python Asyncio,我目前有一个for循环,如下所示 async def process(tasks, num): count = 0 results = [] for task in tasks: if count >= num: break result = await some_async_task(task) if result == 'foo':

我目前有一个for循环,如下所示

async def process(tasks, num):
      count = 0
      results = []
      for task in tasks:
           if count >= num:
               break
           result = await some_async_task(task)
           if result == 'foo':
               continue
           results.append(result)
           count+=1
我想知道我是否可以在这里使用“收集”或“等待”。但我不知道如何在那里实现这些if逻辑?喜欢如果count>=num,我不想不必要地等待任务。
如果有20个任务且num=4,那么我不想全部运行20个任务。

您可以批量处理任务,处理的大小等于您仍然需要的结果数量。如果将此类批处理交给
asyncio.gather()
,它将并行运行它们并保留结果的顺序。例如:

async def process(tasks, num):
    results = []
    task_iter = iter(tasks)
    while len(results) < num:
        next_batch = tuple(itertools.islice(task_iter, num - len(results)))
        if len(next_batch) == 0:
            break
        batch_results = await asyncio.gather(*next_batch)
        results.extend(r for r in batch_results if r == 'foo')
async def进程(任务,num):
结果=[]
任务=国际热核实验堆(任务)
而len(结果)
这可以通过使用来轻松实现。以下是一个工作示例:

import asyncio
from random import random
from aiostream import stream, pipe


async def some_async_task(i):
    await asyncio.sleep(random())
    return i if random() < 0.2 else None


async def process(task_args, n):
    return await (
        stream.iterate(task_args)
        | pipe.map(some_async_task, task_limit=n)
        | pipe.filter(bool)
        | pipe.take(n)
        | pipe.list()
    )


async def main():
    print(await process(task_args=range(100), n=10))


if __name__ == "__main__":
    asyncio.run(main())
还请注意,您可以使用
task\u limit
参数调整可以同时运行的
某些异步任务的数量


免责声明:我是项目维护者。

很好地演示了aiostream,但我不确定它是否符合问题的实际要求。具体来说,使用aiostream时OP的
process()
函数的实现是什么样子的?约束条件是,在给定
num
和当前结果计数的情况下,并行运行的任务不超过所需的数量。@user4815162342哦,我明白了:在
aiostream
版本中,始终有
n
任务运行,直到满足条件,然后取消额外的任务。在您的版本中,最多有
n
个任务正在运行(并且大多数时间都少于该任务),但它保证没有任务将提供不使用的结果。有趣的是,这里有某种权衡,对吗?另请参见我的编辑。是的,不开始多余的工作是我在OP中所说的目标。另一方面,aiostream版本更通用,可能更容易适应不同的情况。我的答案更符合问题(据我所知),没有外部依赖性,可能更快。(如果我在生产中使用这个,我会衡量这个链接的性能——毕竟Python抽象远远不是“零成本”)在我看来,OP要求不要运行所有任务,因为他只需要
n
任务(在我的示例中,运行所有100个任务是没有意义的,因为大约50个任务是获得10个结果所必需的)。但是,我同意您的解决方案足够优雅和简单,可以省去对第三方库的需要:)关于性能,这实际上取决于您的外观:使用异步生成器对CPU的成本肯定更高,但似乎可以安全地假设,大部分时间都花在等待任务完成上。使用您的解决方案,当缺少一些结果时,这些任务可能会一个接一个地运行,并增加运行时间。这就是我之前提到的权衡,没有多余的作业和运行时间。@user4815162342:我接受了有效的答案。事实上,我没有试过另一种反应。
[1, 8, 16, 18, 19, 37, 42, 43, 45, 47]