使用asyncio进行任务充值

时间:2016-11-02 18:07:07

标签: python-3.x python-3.4 python-3.5 python-asyncio aiohttp

在我的项目中,我有一个列表来执行我执行的任务。

loop.run_until_complete(tasks)

然而,有无数的任务,所以目前我分批执行它们。基本上,我有这个:

def get_results(tasks):
    return [result for result in loop.run_until_complete(handle_tasks(tasks))]

while True:
    tasks = get_tasks()
    results = get_results(tasks)

我得到了许多任务,我吃了一个常规函数,它使用一个循环来异步执行这些任务并返回结果。

这种方法有效,但我相信它可以改进。

我想做一些任务充值而不是完成批量任务。

这样的事情:

while True:
    if current_tasks < max_tasks:
        new_tasks = get_tasks(max_tasks - current_tasks)
        add_tasks(new_tasks)
    current_tasks, results = stats_and_results()

我很感激有关如何解决这个问题的任何想法。

谢谢!

1 个答案:

答案 0 :(得分:2)

我们遇到了类似的问题,最后编写了一个小的“Pool”包装器,它接受了作业并使用预定义的并发运行它们。

import asyncio
import sys


class Pool:
    def __init__(self, concurrency):
        self._sem = asyncio.BoundedSemaphore(concurrency)
        self.jobs = []

    async def __aenter__(self):
        return self

    async def __aexit__(self, *_):
        if len(self.jobs) > 0:
            await asyncio.wait(self.jobs)

    def put(self, coro):
        assert asyncio.iscoroutine(coro)
        async def wrapped():
            async with self._sem:
                await coro
        fut = asyncio.ensure_future(wrapped())
        self.jobs.append(fut)

    async def __aiter__(self):
        return self

    async def __anext__(self):
        try:
            coro = self.jobs.pop(0)
        except IndexError:
            raise StopAsyncIteration()
        else:
            return await coro

然后您可以这样使用它:

async def main():
    pool = Pool(10)
    for task in get_tasks():
        pool.put(task)
    async for result in pool:
        print('got', result)

这将安排所有任务,同时运行最多10个任务并返回结果,因为它们来到main()协程