Loading

async.gather()

在 Python 的 asyncio 模块中,await asyncio.gather(*tasks)await asyncio.wait(task_list) 都用于等待多个异步任务完成,但它们在功能、用法和行为上有一些细微的区别。下面我会详细解释它们的不同之处。

1. asyncio.gather(*tasks)

asyncio.gather(*tasks) 是一个非常常用的方法,用于并发执行多个异步任务,并等待它们全部完成。它会返回一个结果列表,其中每个元素对应每个任务的返回值。如果某个任务抛出了异常,gather() 会立即抛出异常,且会在所有任务中传播异常。

特点

  • 返回值: 如果所有任务成功完成,gather() 返回一个包含每个任务结果的列表。
  • 异常传播: 如果某个任务抛出了异常,gather() 会立刻抛出该异常,并且不会返回其他任务的结果,除非在捕获异常的上下文中处理它。
  • 顺序保证: 返回的结果列表的顺序与任务传入的顺序一致,即使任务的执行顺序不同,返回值的顺序也会与传入时的顺序一致。

示例

import asyncio

async def task1():
    await asyncio.sleep(1)
    return "Task 1 complete"

async def task2():
    await asyncio.sleep(2)
    return "Task 2 complete"

async def main():
    results = await asyncio.gather(task1(), task2())
    print(results)  # ['Task 1 complete', 'Task 2 complete']

asyncio.run(main())

如果某个任务抛出异常,gather() 会立刻传播该异常。

async def task1():
    await asyncio.sleep(1)
    return "Task 1 complete"

async def task2():
    await asyncio.sleep(2)
    raise ValueError("Task 2 failed!")

async def main():
    try:
        results = await asyncio.gather(task1(), task2())
    except Exception as e:
        print(f"Error: {e}")

asyncio.run(main())  # Output: Error: Task 2 failed!

2. asyncio.wait(task_list)

asyncio.wait(task_list) 是一个低级的 API,用于等待一个任务集合中的任务完成。它返回一个包含两组任务的元组:一组是已经完成的任务,另一组是仍然未完成的任务。wait() 更加灵活,可以用于控制任务的执行状态,但它并不会返回任务的结果。

特点

  • 返回值: 返回一个二元组 (done, pending),其中 done 是已完成的任务,pending 是仍然在等待的任务。donepending 都是 set 类型。
  • 异常处理: asyncio.wait() 不会自动抛出异常。你需要单独处理任务中的异常。
  • 可自定义行为: asyncio.wait() 允许你设置如何等待任务完成,比如设置 timeout 或者通过 return_when 参数来控制如何完成等待(例如:asyncio.FIRST_COMPLETEDasyncio.FIRST_EXCEPTION)。

示例

import asyncio

async def task1():
    await asyncio.sleep(1)
    return "Task 1 complete"

async def task2():
    await asyncio.sleep(2)
    return "Task 2 complete"

async def main():
    tasks = [task1(), task2()]
    done, pending = await asyncio.wait(tasks)

    # 查看已经完成的任务
    for task in done:
        print(task.result())  # Output: Task 1 complete / Task 2 complete

asyncio.run(main())

asyncio.wait() 的更多控制

asyncio.wait() 提供了额外的控制选项,通过 return_when 参数,你可以选择等待所有任务完成或等待第一个任务完成。

done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
  • asyncio.FIRST_COMPLETED:返回第一个完成的任务。
  • asyncio.FIRST_EXCEPTION:返回第一个抛出异常的任务。
  • asyncio.ALL_COMPLETED:等待所有任务完成(这是默认行为)。

主要区别

特性 asyncio.gather(*tasks) asyncio.wait(task_list)
返回值 返回任务的结果列表。 返回二元组 (done, pending),分别是已完成的任务和未完成的任务。
异常处理 如果有任务抛出异常,gather 会立刻抛出异常,其他任务的结果不会返回。 需要手动处理任务的异常。
任务顺序 返回的结果顺序与传入任务的顺序一致。 不保证顺序。
控制选项 没有 return_when 选项,等待所有任务完成。 提供 return_when 参数,允许等待某个特定的任务状态。
适用场景 用于需要获取所有任务结果并且确保任务按顺序完成的情况。 用于需要更细粒度控制任务执行过程(如超时、等待第一个完成等)的情况。

总结

  • asyncio.gather() 是一个更高级的、用于等待任务完成并收集结果的方法,适合于需要获取所有任务结果并保证顺序的情况。
  • asyncio.wait() 提供更多控制和灵活性,适合于需要精确控制任务执行顺序、等待任务完成状态或需要处理任务异常的情况。

选择哪个方法取决于你的需求:

  • 如果你只需要等待任务完成并获取结果,使用 gather() 更简单。
  • 如果你需要更多控制(比如超时、处理异常或等待第一个任务完成),则使用 wait()
posted @ 2024-12-21 12:21  一只大学生  阅读(524)  评论(0)    收藏  举报