Python异步编程实战:asyncio入门到精通
Python的asyncio模块是实现异步编程的核心工具。随着Python 3.5引入async/await语法,异步编程变得越来越流行。本文将从基础概念到高级用法,带你全面掌握asyncio。
一、什么是异步编程
同步 vs 异步
同步编程:代码按照顺序执行,一个任务完成后才开始下一个。如果遇到IO操作(如网络请求、文件读写),程序会阻塞等待。
异步编程:程序可以在等待IO操作时切换执行其他任务,充分利用等待时间,提高程序的整体效率。
为什么需要异步
- IO密集型任务:网络请求、文件读写、数据库查询等
- 高并发场景:Web服务器、爬虫、API网关等
- 资源利用:单线程也能处理大量并发连接
asyncio的优势
- 单线程运行,无锁竞争
- 代码可读性好(相比回调地狱)
- Python官方标准库,无需额外依赖
- 与同步代码可以共存
二、基础概念
1. 协程(Coroutine)
协程是asyncio的基础。使用 async def 定义协程函数:
import asyncio
async def hello():
print('Hello')
await asyncio.sleep(1) # 异步等待1秒
print('World')
# 运行协程
asyncio.run(hello())
2. await 关键字
await 用于等待一个协程或可等待对象。在await处,程序会挂起并让出控制权:
async def fetch_data():
print('开始获取数据...')
await asyncio.sleep(2) # 模拟网络请求
print('数据获取完成')
return {'name': '张三', 'age': 25}
3. 事件循环(Event Loop)
事件循环是asyncio的核心,负责调度和执行协程:
import asyncio
async def main():
print('主协程开始')
await asyncio.sleep(1)
print('主协程结束')
# Python 3.7+
asyncio.run(main())
三、并发执行
1. asyncio.gather()
同时执行多个协程:
import asyncio
import time
async def task(name, delay):
print(f'任务{name}开始')
await asyncio.sleep(delay)
print(f'任务{name}完成')
return f'{name}的结果'
async def main():
start = time.time()
# 并发执行3个任务
results = await asyncio.gather(
task('A', 2),
task('B', 1),
task('C', 3)
)
print(f'所有任务完成,耗时: {time.time() - start:.2f}秒')
print(f'结果: {results}')
asyncio.run(main())
2. asyncio.create_task()
创建后台任务:
async def background_task():
while True:
print('后台任务运行中...')
await asyncio.sleep(5)
async def main():
# 创建后台任务
task = asyncio.create_task(background_task())
# 主逻辑继续执行
print('主逻辑执行中...')
await asyncio.sleep(3)
print('主逻辑完成')
# 取消后台任务
task.cancel()
asyncio.run(main())
四、超时控制
1. asyncio.wait_for()
设置单个协程的超时时间:
async def slow_task():
await asyncio.sleep(10)
return '完成'
async def main():
try:
result = await asyncio.wait_for(slow_task(), timeout=3.0)
except asyncio.TimeoutError:
print('任务超时!')
五、实战示例
1. 异步HTTP请求
使用 aiohttp 库:
import asyncio
import aiohttp
async def fetch_url(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
urls = [
'https://httpbin.org/get',
'https://httpbin.org/ip',
'https://httpbin.org/user-agent',
]
async with aiohttp.ClientSession() as session:
tasks = [fetch_url(session, url) for url in urls]
results = await asyncio.gather(*tasks)
for url, result in zip(urls, results):
print(f'{url}: {result[:100]}...')
asyncio.run(main())
六、最佳实践
1. 不要在协程中使用阻塞操作
# 错误示范
async def bad_example():
import time
time.sleep(5) # 这会阻塞整个事件循环!
# 正确做法
async def good_example():
await asyncio.sleep(5) # 异步等待
2. 使用asyncio.run()作为入口
# Python 3.7+
async def main():
# 你的异步代码
pass
if __name__ == '__main__':
asyncio.run(main())
七、总结
asyncio是Python异步编程的强大工具。掌握它需要理解:
- 协程:使用async/await定义和执行
- 事件循环:调度和执行协程的核心
- 并发执行:gather、create_task、wait
- 超时控制:wait_for、shield
- 最佳实践:避免阻塞、合理错误处理
异步编程能显著提升IO密集型应用的性能。希望这篇教程对你有帮助!