9.4 异步编程与 asyncio
概述
异步编程是一种编程范式,旨在提高程序的并发性和响应性,特别是在 I/O 密集型任务中。Python 通过 asyncio 模块提供了对异步编程的原生支持。asyncio 是 Python 3.4 引入的标准库,用于编写单线程并发代码,使用 async 和 await 关键字来定义和管理异步任务。
异步编程的核心概念
协程(Coroutine)
协程是异步编程的基本单元,使用async def定义的函数称为协程函数。协程函数返回一个协程对象,该对象可以通过await关键字来等待其执行完成。async def my_coroutine(): print("Start coroutine") await asyncio.sleep(1) print("End coroutine")事件循环(Event Loop)
事件循环是异步编程的核心,负责调度和执行协程。asyncio提供了run_until_complete和run_forever等方法来启动事件循环。import asyncio async def main(): await my_coroutine() asyncio.run(main())任务(Task)
任务是对协程的进一步封装,用于并发执行多个协程。通过asyncio.create_task()可以将协程转换为任务。async def main(): task1 = asyncio.create_task(my_coroutine()) task2 = asyncio.create_task(my_coroutine()) await task1 await task2Future 对象
Future是一个低级别的对象,表示异步操作的最终结果。任务是基于Future实现的。
asyncio 的常用功能
并发执行任务
使用asyncio.gather()可以并发执行多个协程。async def main(): await asyncio.gather( my_coroutine(), my_coroutine() )超时控制
使用asyncio.wait_for()可以为异步操作设置超时。async def main(): try: await asyncio.wait_for(my_coroutine(), timeout=0.5) except asyncio.TimeoutError: print("Timeout!")任务取消
可以通过task.cancel()取消正在运行的任务。async def main(): task = asyncio.create_task(my_coroutine()) await asyncio.sleep(0.5) task.cancel() try: await task except asyncio.CancelledError: print("Task cancelled")
异步编程的优势
- 高效利用资源:异步编程可以在单线程中处理大量 I/O 操作,避免线程切换的开销。
- 提高响应性:适用于需要快速响应的场景,如 Web 服务器和实时数据处理。
- 简化代码结构:通过
async和await关键字,代码逻辑更加清晰。
异步编程的挑战
- 调试复杂性:异步代码的调试比同步代码更复杂,因为执行顺序可能不直观。
- 兼容性问题:并非所有库都支持异步操作,可能需要使用适配器或替代方案。
- 学习曲线:理解事件循环、协程和任务的概念需要一定的时间。
示例:异步 HTTP 请求
以下是一个使用 aiohttp 库进行异步 HTTP 请求的示例:
import aiohttp
import asyncio
async def fetch(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
async def main():
urls = [
"https://example.com",
"https://example.org",
"https://example.net"
]
tasks = [fetch(url) for url in urls]
results = await asyncio.gather(*tasks)
for result in results:
print(result[:100]) # 打印前 100 个字符
asyncio.run(main())
总结
异步编程是 Python 中处理高并发和高性能任务的重要工具。通过 asyncio 模块,开发者可以轻松编写高效的异步代码。掌握异步编程的核心概念和技巧,能够显著提升程序的性能和响应能力。
