Python3 `asyncio` — 异步 I/O,事件循环和并发工具
Python3 asyncio — 异步 I/O,事件循环和并发工具
在 Python 编程中,asyncio 是用于编写并发代码的标准库。它使得 Python 程序能够高效地处理 I/O 密集型任务,如网络请求、文件读取等,特别是在需要同时处理大量并发任务时。asyncio 的核心思想是异步 I/O,基于事件循环机制,让多个任务在同一个线程中并发执行,而不需要多线程或多进程的复杂处理。
本文将详细介绍 Python3 中的 asyncio 模块,包括如何使用事件循环、异步 I/O 任务和并发工具,以及通过代码示例帮助你掌握其核心概念和应用场景。
一、什么是 asyncio?
asyncio 是 Python 3.3 引入的标准库,用于支持异步编程。它提供了一个事件循环机制,可以在同一个线程中调度和执行多个 I/O 密集型任务。asyncio 使得 Python 能够以非阻塞的方式运行多个任务,从而提高了处理并发任务的效率。
1.1 主要概念
- 事件循环(Event Loop):是 asyncio的核心,负责调度任务和执行异步操作。它会不断地检查哪些任务已经完成,哪些任务需要等待,并在适当的时机运行它们。
- 协程(Coroutines):是 Python 中定义的异步函数,它通过 async关键字声明,await关键字用于暂停协程的执行,等待某个异步操作完成。
- 任务(Tasks):协程的封装,可以将多个协程调度并行执行。
- Future:表示将来某个时刻完成的异步操作的结果。Future是一个特殊的对象,它用来表示一个尚未完成的操作的结果。
二、事件循环(Event Loop)
事件循环是 asyncio 的基础,控制着异步操作的执行流程。在 asyncio 中,程序通过事件循环来执行多个协程。通常情况下,你不需要手动创建事件循环,asyncio.run() 函数会自动为你创建并运行事件循环。
2.1 使用 asyncio.run() 启动事件循环
import asyncio
async def say_hello():
    print("Hello, world!")
# 启动事件循环
asyncio.run(say_hello())解释:
- 使用 async def定义一个异步协程say_hello()。
- asyncio.run()启动事件循环,执行- say_hello()协程。
2.2 事件循环中的异步任务
在事件循环中,多个异步任务可以并发执行。asyncio.create_task() 用于将协程包装成任务,并将其调度到事件循环中执行。
import asyncio
async def task1():
    print("Task 1 started")
    await asyncio.sleep(2)
    print("Task 1 finished")
async def task2():
    print("Task 2 started")
    await asyncio.sleep(1)
    print("Task 2 finished")
async def main():
    # 创建并启动任务
    task1_obj = asyncio.create_task(task1())
    task2_obj = asyncio.create_task(task2())
    
    # 等待任务完成
    await task1_obj
    await task2_obj
# 启动事件循环
asyncio.run(main())解释:
- asyncio.create_task()将- task1()和- task2()协程创建为任务,并交给事件循环。
- await等待任务完成,确保事件循环在所有任务完成后才结束。
输出:
Task 1 started
Task 2 started
Task 2 finished
Task 1 finished从输出可以看出,两个任务并发执行,task2() 完成后 task1() 继续执行。
三、异步 I/O 操作
异步 I/O 操作允许我们在等待 I/O 操作完成时不阻塞整个程序。asyncio 提供了异步版本的 I/O 操作,例如 asyncio.sleep()、asyncio.gather() 等。
3.1 asyncio.sleep():模拟 I/O 操作
asyncio.sleep() 是一个模拟延时的异步操作。它不会阻塞事件循环,在等待过程中可以执行其他任务。
import asyncio
async def async_task(name, seconds):
    print(f"Task {name} started")
    await asyncio.sleep(seconds)
    print(f"Task {name} finished after {seconds} seconds")
async def main():
    # 启动多个异步任务
    await asyncio.gather(
        async_task("A", 2),
        async_task("B", 1),
        async_task("C", 3)
    )
# 启动事件循环
asyncio.run(main())解释:
- asyncio.gather()用来并发执行多个异步任务,并等待所有任务完成。
- asyncio.sleep()使当前协程暂停一段时间,模拟 I/O 操作。
输出:
Task A started
Task B started
Task C started
Task B finished after 1 seconds
Task A finished after 2 seconds
Task C finished after 3 seconds四、并发工具:asyncio.gather() 和 await
4.1 asyncio.gather():并发执行多个协程
asyncio.gather() 可以并发执行多个协程,并等待它们的结果。它非常适用于需要并行执行多个任务的场景。
import asyncio
async def fetch_data(url):
    print(f"Fetching data from {url}")
    await asyncio.sleep(2)  # 模拟 I/O 操作
    return f"Data from {url}"
async def main():
    urls = ["https://example.com", "https://google.com", "https://github.com"]
    # 同时请求多个网址
    results = await asyncio.gather(*(fetch_data(url) for url in urls))
    print(results)
# 启动事件循环
asyncio.run(main())解释:
- asyncio.gather()用于并行执行多个协程,返回它们的结果。
- *(fetch_data(url) for url in urls)使用生成器表达式创建多个协程。
输出:
Fetching data from https://example.com
Fetching data from https://google.com
Fetching data from https://github.com
Data from https://example.com
Data from https://google.com
Data from https://github.com4.2 任务的结果处理
asyncio.gather() 会返回所有任务的结果,可以直接对结果进行处理。
import asyncio
async def task(name, seconds):
    await asyncio.sleep(seconds)
    return f"Task {name} finished after {seconds} seconds"
async def main():
    tasks = [
        asyncio.create_task(task("A", 1)),
        asyncio.create_task(task("B", 2)),
        asyncio.create_task(task("C", 3))
    ]
    
    # 获取任务结果
    results = await asyncio.gather(*tasks)
    print(results)
# 启动事件循环
asyncio.run(main())解释:
- asyncio.create_task()创建任务并并发执行。
- asyncio.gather()返回任务的执行结果。
输出:
['Task A finished after 1 seconds', 'Task B finished after 2 seconds', 'Task C finished after 3 seconds']五、总结
asyncio 是 Python3 提供的一个强大工具,用于简化异步 I/O 操作和并发编程。通过事件循环和协程,asyncio 能够高效地执行多个任务而不阻塞程序的执行。主要功能包括:
- 异步 I/O 操作,避免阻塞。
- 使用 async和await定义协程。
- 使用 asyncio.create_task()调度任务。
- 使用 asyncio.gather()并发执行多个协程。
理解并掌握 asyncio 的基本概念和用法,可以帮助你高效地处理 I/O 密集型任务,提升程序的并发能力。
希望这篇教程能帮助你更好地理解 Python 中的异步编程,并应用到实际项目中!
评论已关闭