asyncio运行多个任务,同时保留顺序和处理错误

时间:2017-09-02 10:54:55

标签: python python-3.x python-asyncio

我的函数run_tasks(all_tasks, window_size),它接受​​asyncio个任务的生成器,并在以下情况下返回其值:

  1. 同时从window_size
  2. 运行每个 窗口 (大小为all_tasks
  3. 保留返回结果的顺序(all_tasks[i]结果为results[i]
  4. 处理每次运行的异常
  5. 我目前的实施:

    import asyncio
    from itertools import islice
    
    
    # run all tasks and return their results in the same order
    # window is the max number of tasks that will run in parallel
    def run_tasks(all_tasks, window_size=4):
        loop = asyncio.get_event_loop()
    
        while True:
            window_tasks = list(islice(all_tasks, window_size))
            if not window_tasks:
                break
    
            futures = asyncio.wait(window_tasks, loop=loop)
            finished, unfinished = loop.run_until_complete(futures)
    
            # sort finished tasks by their launch order.
            # removing this line makes returned tasks unordered
            finished = sorted(finished, key=lambda f: window_tasks.index(f._coro))
    
            for finished_task in finished:
                try:
                    yield finished_task.result()
                except Exception as e:
                    yield repr(e)
    
    # Example Usage:
    
    # a coroutine that sometime raises exception
    async def sleepy(i):
        print(f'{i} started')
        await asyncio.sleep(10 - i)
        print(f'{i} finished')
        if i == 5:
            raise ValueError('5 is the worst')
        return i
    
    # a generator of tasks
    all_tasks = (sleepy(i) for i in range(10))
    
    for result in list(run_tasks(all_tasks)):
        print(result)
    

    问题

    我的实现问题是,我无法在不访问f._coro对象的内部属性asyncio.Task的情况下找到对任务进行排序的方法。

    # removing this line makes returned tasks unordered
    finished = sorted(finished, key=lambda f: window_tasks.index(f._coro))
    

    我可以使用asyncio.gather(*tasks),但这不会处理错误。

    我愿意接受有关如何为run_tasks()实施此三个属性而无法访问f._coro的建议。

1 个答案:

答案 0 :(得分:2)

如果您指定了关键字参数void main(){ gl_PointSize = 100.; gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.); } ,则

asyncio.gather can会返回错误。为了区分真实异常和异常对象返回作为协程的结果,您可以使用return_exceptionswindow_tasks包裹在任务中:

ensure_future