Python异步 详细介绍
Python 异步编程的核心是语法 + 事件循环,核心价值是提升IO 密集型任务的执行效率;核心组件:协程函数(async def)、Task(并行调度)、事件循环(调度核心);典型应用:异步网络请求、异步文件读写、异步 Web 服务(FastAPI);避坑关键:避免混用同步阻塞代码,正确使用await,并发竞争用;选型原则:IO 密集用异步,CPU 密集用多进程,简单 IO 场景可考虑多线程。
·
一、异步编程的核心本质(先搞懂「为什么」)
1. 同步 vs 异步:核心差异
- 同步编程:代码按顺序执行,遇到耗时 IO(网络请求、文件读写、数据库操作)时,线程会阻塞等待结果,CPU 闲置。例:10 个网络请求串行执行,每个耗时 2 秒,总耗时≈20 秒。
- 异步编程:代码执行到耗时 IO 时,会让出 CPU 控制权,去执行其他任务;等 IO 有结果后,再回调处理,CPU 全程不闲置。例:10 个网络请求异步执行,总耗时≈2 秒(仅等待最长的那个请求)。
2. 异步编程的核心目标
解决IO 密集型任务的效率问题(如爬虫、API 服务、数据库批量操作),而非 CPU 密集型任务(纯计算用多进程更合适)。
二、Python 异步的核心组件(从基础到核心)
1. 基础语法:async/await(Python 3.5+)
| 关键字 / 函数 | 作用 | 用法示例 |
|---|---|---|
async def |
定义协程函数(Coroutine Function),调用后返回协程对象,不立即执行 | ```python |
| async def async_task(): | ||
| await asyncio.sleep(2) | ||
| return "完成" |
|
| `await` | 暂停协程执行,等待「可等待对象」完成,期间让出CPU;**仅能在协程函数内使用** | 见上方示例,等待`asyncio.sleep(2)`(模拟耗时IO) |
| `asyncio.run()` | 启动事件循环,执行指定协程(程序入口常用) | ```python
result = asyncio.run(async_task())
print(result) # 输出:完成
``` |
#### 2. 核心驱动:事件循环(Event Loop)
- **本质**:异步编程的「总指挥」,负责调度所有协程、管理IO事件、处理回调。
- **核心工作流程**:
```mermaid
graph TD
A[启动事件循环] --> B[将协程包装为Task加入队列]
B --> C{是否有可执行任务?}
C -- 是 --> D[执行任务直到遇到await]
D --> E[让出CPU,处理下一个任务]
C -- 否 --> F[等待IO事件触发]
F --> G[IO完成,回调对应的任务继续执行]
G --> C
- 手动操控事件循环(进阶):
python
运行
import asyncio async def task1(): print("任务1开始") await asyncio.sleep(1) print("任务1结束") async def task2(): print("任务2开始") await asyncio.sleep(2) print("任务2结束") # 手动创建事件循环(适合复杂场景) loop = asyncio.get_event_loop() # 同时执行多个协程 tasks = [task1(), task2()] loop.run_until_complete(asyncio.wait(tasks)) loop.close()
3. 任务管理:Task与Future
- Task:协程的「可执行包装器」,加入事件循环后立即调度(并行执行)。核心用法:
asyncio.create_task(coro)(Python 3.7+)python
运行
async def main(): # 创建2个Task,立即并行执行 t1 = asyncio.create_task(task1()) t2 = asyncio.create_task(task2()) # 等待所有Task完成 await t1 await t2 asyncio.run(main()) # 输出: # 任务1开始 # 任务2开始 # 任务1结束 # 任务2结束 - Future:表示「未来完成的结果」,Task 是 Future 的子类,一般无需手动创建,底层使用。
三、实战场景:异步编程的典型应用
1. 异步网络请求(最常用场景)
需安装异步请求库:pip install aiohttp
python
运行
import aiohttp
import asyncio
# 异步请求单个URL
async def fetch_url(session, url):
async with session.get(url) as response:
return await response.text() # 等待响应结果
# 批量异步请求
async def batch_fetch(urls):
# 创建异步会话(复用连接,提升效率)
async with aiohttp.ClientSession() as session:
# 创建所有请求任务
tasks = [asyncio.create_task(fetch_url(session, url)) for url in urls]
# 等待所有任务完成,返回结果列表
results = await asyncio.gather(*tasks)
return results
# 测试
if __name__ == "__main__":
urls = [
"https://httpbin.org/get?name=1",
"https://httpbin.org/get?name=2",
"https://httpbin.org/get?name=3"
]
# 执行异步批量请求
results = asyncio.run(batch_fetch(urls))
print(f"共请求{len(results)}个URL,第一个结果:{results[0][:50]}")
2. 异步文件读写(Python 3.7+)
python
运行
import asyncio
async def async_read_file(file_path):
# 异步打开文件(需使用aiofiles库,Python内置open是同步的)
# 安装:pip install aiofiles
import aiofiles
async with aiofiles.open(file_path, 'r', encoding='utf-8') as f:
content = await f.read()
return content
async def main():
content = await async_read_file("test.txt")
print(f"文件内容:{content}")
asyncio.run(main())
3. 异步 Web 服务(FastAPI)
FastAPI 是天生支持异步的 Web 框架,性能远超 Flask:
python
运行
from fastapi import FastAPI
import asyncio
app = FastAPI()
# 异步接口
@app.get("/async-task")
async def async_task():
await asyncio.sleep(2) # 模拟耗时操作
return {"message": "异步任务完成"}
# 启动服务:uvicorn main:app --reload
# 访问http://127.0.0.1:8000/async-task,服务可同时处理多个请求(无阻塞)
四、异步编程的常见坑与避坑指南
-
混用同步阻塞代码:异步函数内调用
time.sleep()、requests.get()等同步阻塞函数,会导致整个事件循环卡住!✅ 解决方案:用异步替代(asyncio.sleep()替代time.sleep(),aiohttp替代requests)。 -
await使用错误:- 错误:在同步函数内用
await; - 错误:直接调用协程函数(如
task1())而不await或create_task;✅ 解决方案:await仅在async def函数内使用,协程必须通过asyncio.run()/create_task()执行。
- 错误:在同步函数内用
-
异步锁(解决并发竞争):多任务修改同一变量时,需用
asyncio.Lock()保证原子性:python
运行
async def update_num(lock, num): async with lock: # 加锁 num += 1 await asyncio.sleep(0.1) return num async def main(): lock = asyncio.Lock() num = 0 tasks = [asyncio.create_task(update_num(lock, num)) for _ in range(10)] results = await asyncio.gather(*tasks) print(f"最终结果:{results[-1]}") # 输出:10(无锁可能小于10) asyncio.run(main())
五、异步 vs 多线程 / 多进程:选型建议
| 编程范式 | 适用场景 | 优势 | 劣势 |
|---|---|---|---|
| 异步编程 | IO 密集型任务(网络、文件、数据库) | 轻量级(无线程切换开销)、效率最高 | 学习曲线稍陡、依赖异步库 |
| 多线程 | IO 密集型任务(简单场景) | 语法简单、兼容同步代码 | GIL 限制(CPU 密集型无优势)、线程切换开销 |
| 多进程 | CPU 密集型任务(计算、数据处理) | 利用多核 CPU、无 GIL 限制 | 内存占用高、进程通信复杂 |
总结
- Python 异步编程的核心是
async/await语法 + 事件循环,核心价值是提升IO 密集型任务的执行效率; - 核心组件:协程函数(
async def)、Task(并行调度)、事件循环(调度核心); - 典型应用:异步网络请求、异步文件读写、异步 Web 服务(FastAPI);
- 避坑关键:避免混用同步阻塞代码,正确使用
await,并发竞争用asyncio.Lock(); - 选型原则:IO 密集用异步,CPU 密集用多进程,简单 IO 场景可考虑多线程。
更多推荐

所有评论(0)