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.com
4.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 中的异步编程,并应用到实际项目中!