如何使用python的异步处理库asyncio解决问题

110 阅读3分钟

1. 简介

asyncio.as_completed 是 Python 中用于异步编程的重要工具之一,属于 asyncio 库。它允许开发者并发执行多个协程,并按照完成顺序返回结果。这使得它非常适合实时处理任务结果的场景。

2. 基本用法

2.1 示例代码

import asyncio

async def task1():
    print("任务1开始执行")
    await asyncio.sleep(2)  # 等待2秒
    print("任务1执行完毕")
    return "任务1结果"

async def task2():
    print("任务2开始执行")
    await asyncio.sleep(1)  # 等待1秒
    print("任务2执行完毕")
    return "任务2结果"

async def main():
    tasks = [task1(), task2()]
    for coro in asyncio.as_completed(tasks):
        result = await coro
        print(f"任务完成,结果: {result}")

asyncio.run(main())

在这个例子中,task2 会先完成,因为它的等待时间更短。

2.2 特点

  • 按完成顺序返回结果asyncio.as_completed 按照协程完成的顺序返回结果,而不是按照传入的顺序。
  • 立即处理结果:可以在协程完成时立即处理结果,而不需要等待所有协程完成。
  • 异常处理:如果某个协程抛出异常,as_completed 会立即返回该异常,并继续处理其他协程。

3. 与 asyncio.gather 的区别

特征asyncio.gatherasyncio.as_completed
返回结果顺序按传入顺序返回结果按完成顺序返回结果
异常处理如果某个协程抛出异常,立即停止等待其他协程并抛出异常如果某个协程抛出异常,立即返回该异常并继续处理其他协程
适用场景适合需要等待所有协程完成并按顺序处理结果的场景适合需要按完成顺序处理结果的场景

4. 适用场景

asyncio.as_completed 适合实时处理任务结果的场景,例如在数据爬取后立即进行机器学习模型计算。它允许开发者在任务完成后立即开始下一步操作,而不需要等待所有任务完成。

5. 总结

asyncio.as_completed 是一种强大的工具,用于并发执行协程并实时处理结果。通过其灵活的异常处理和按完成顺序返回结果的特性,它在实时处理任务结果的场景中尤其有用。

6. 进一步案例

6.1 超时处理

asyncio.as_completed 可以通过设置超时时间来处理任务超时的情况。例如:

import asyncio

async def task1():
    await asyncio.sleep(5)
    return "任务1结果"

async def task2():
    await asyncio.sleep(1)
    return "任务2结果"

async def main():
    tasks = [task1(), task2()]
    for coro in asyncio.as_completed(tasks, timeout=3):
        try:
            result = await coro
            print(f"任务完成,结果: {result}")
        except asyncio.TimeoutError:
            print("任务超时")

asyncio.run(main())

在这个例子中,如果任务超过3秒未完成,就会抛出超时异常。

6.2 异常处理

如果某个协程抛出异常,as_completed 会立即返回该异常,并继续处理其他协程。例如:

import asyncio

async def task1():
    await asyncio.sleep(2)
    raise ValueError("任务1异常")
    return "任务1结果"

async def task2():
    await asyncio.sleep(1)
    return "任务2结果"

async def main():
    tasks = [task1(), task2()]
    for coro in asyncio.as_completed(tasks):
        try:
            result = await coro
            print(f"任务完成,结果: {result}")
        except ValueError as e:
            print(f"任务异常: {e}")

asyncio.run(main())

在这个例子中,当 task1 抛出异常时,task2 的结果仍会被处理。