Python AsyncIO
什么是异步IO?
异步IO (AsyncIO) 是Python中处理并发操作的一种方式,它允许程序在等待I/O操作完成时执行其他任务,而不是一直等待当前操作完成。这种编程模式在处理网络请求、文件操作和其他I/O密集型任务时特别有效,可以显著提升程序性能。
备注
AsyncIO 并不是多线程,而是使用单线程通过协程(coroutines)进行任务切换,从而实现并发效果。
同步与异步的对比
为了理解AsyncIO的优势,让我们先对比同步和异步编程模式:
AsyncIO 的核心概念
1. 协程 (Coroutines)
协程是实现Python异步编程的基础。它们类似于函数,但可以在执行过程中暂停,允许其他代码运行,然后恢复执行。
在Python 3.5+中,协程是通过async def
语法定义的:
async def my_coroutine():
print("开始执行")
await asyncio.sleep(1) # 暂停协程,允许其他协程运行
print("执行完成")
2. await 关键字
await
关键字用于暂停协程,直到被等待的对象完成。只能在协程函数中使用:
async def fetch_data():
print("开始获取数据")
await asyncio.sleep(2) # 模拟网络延迟
print("数据获取完成")
return {"data": "这是一些数据"}
async def main():
result = await fetch_data() # 等待fetch_data完成并获取结果
print(f"获得结果: {result}")
3. 事件循环 (Event Loop)
事件循环是AsyncIO的核心,它管理协程的执行、网络IO操作、子进程和其他事件。
import asyncio
async def main():
print("Hello")
await asyncio.sleep(1)
print("World")
# 获取事件循环并运行协程
asyncio.run(main()) # Python 3.7+的推荐方法
使用AsyncIO的基本步骤
步骤1: 导入asyncio模块
import asyncio
步骤2: 定义异步函数
async def say_after(delay, what):
await asyncio.sleep(delay)
print(what)
步骤3: 创建并运行协程
async def main():
print(f"开始时间: {asyncio.get_event_loop().time()}")
await say_after(1, '你好')
await say_after(2, '世界')
print(f"结束时间: {asyncio.get_event_loop().time()}")
asyncio.run(main())
输出:
开始时间: 0.0
你好
世界
结束时间: 3.0103720220001537
这个例子是顺序执行的,两个任务总共花费了约3秒。让我们看看如何并发执行:
步骤4: 并发执行多个协程
async def main():
print(f"开始时间: {asyncio.get_event_loop().time()}")
# 使用asyncio.gather并发执行多个协程
await asyncio.gather(
say_after(1, '你好'),
say_after(2, '世界')
)
print(f"结束时间: {asyncio.get_event_loop().time()}")
asyncio.run(main())
输出:
开始时间: 0.0
你好
世界
结束时间: 2.0031230439997465
现在两个任务并发执行,总时间只有约2秒(由最长的任务决定)。
AsyncIO常用功能
1. asyncio.gather() - 并发执行多个协程
async def main():
# 同时执行多个任务并收集所有结果
results = await asyncio.gather(
get_weather("北京"),
get_weather("上海"),
get_weather("广州")
)
for city, temp in results:
print(f"{city}: {temp}°C")
2. asyncio.wait_for() - 设置超时
async def main():
try:
# 如果get_weather超过2秒未完成,会抛出TimeoutError
result = await asyncio.wait_for(get_weather("北京"), timeout=2.0)
print(f"北京: {result}°C")
except asyncio.TimeoutError:
print("请求超时")
3. asyncio.create_task() - 创建任务
async def main():
# 创建任务后立即运行在后台
task1 = asyncio.create_task(say_after(1, '你好'))
task2 = asyncio.create_task(say_after(2, '世界'))
print("任务已创建")
# 此处可以执行其他代码
# 等待任务完成
await task1
await task2
4. asyncio.sleep() - 异步等待
async def delayed_greeting(name):
print(f"准备问候 {name}")
await asyncio.sleep(1) # 非阻塞延迟
print(f"你好, {name}!")