大家好,我是船长。
最近Manus AI大火,让船长意识到一个趋势:AI在抢人类的执行工作,而Python异步编程,是让你代码"自己跑"的关键技术。
今天不聊AI,来聊技术。
什么是异步编程?
先从一个场景说起。
你要从10个API获取数据,传统的同步写法是这样的:
# 同步写法:一个个请求串行执行
for api in apis:
data = requests.get(api) # 每次等待网络返回
results.append(data)
# 10个API × 每次1秒 = 10秒
改成异步后:
import asyncio
import aiohttp
async def fetch_all(apis):
async with aiohttp.ClientSession() as session:
tasks = [fetch(session, api) for api in apis]
return await asyncio.gather(*tasks)
# 10个API并发执行 = 约1秒(取决于最慢那个)
异步的本质:IO等待时切换任务,而不是傻等。
场景1:批量API请求(最高频场景)
完整代码示例:
import asyncio
import aiohttp
import time
async def fetch_one(session, url, semaphore):
async with semaphore: # 限流:最多同时10个请求
async with session.get(url) as response:
return await response.json()
async def fetch_all(urls, max_concurrent=10):
semaphore = asyncio.Semaphore(max_concurrent)
async with aiohttp.ClientSession() as session:
tasks = [fetch_one(session, url, semaphore) for url in urls]
return await asyncio.gather(*tasks, return_exceptions=True)
# 使用
start = time.time()
results = asyncio.run(fetch_all(urls, max_concurrent=20))
print(f"耗时: {time.time() - start:.2f}秒")
关键点解读:
1. Semaphore限流:防止并发太高被API限流或打挂服务器
2. return_exceptions=True:单个请求失败不影响其他请求
3. ClientSession复用:建立连接池,复用TCP连接
场景2:异步文件操作
处理大量本地文件时,aiofiles是异步文件操作的首选:
import asyncio
import aiofiles
async def process_file(filepath):
async with aiofiles.open(filepath, 'r') as f:
content = await f.read()
# 处理内容...
return processed
async def batch_process(filepaths):
return await asyncio.gather(*[process_file(f) for f in filepaths])
场景3:异步数据库操作
用databases库实现异步数据库操作,配合SQLAlchemy:
import asyncio
from databases import Database
db = Database("postgresql://localhost/mydb")
async def batch_insert(records):
await db.connect()
query = "INSERT INTO users(id, name) VALUES (:id, :name)"
await db.execute_many(query, records)
await db.disconnect()
场景4:异步定时任务
用APScheduler配合异步函数:
import asyncio
from apscheduler.schedulers.asyncio import AsyncIOScheduler
async def my_task():
# 异步任务逻辑
await fetch_and_process()
scheduler = AsyncIOScheduler()
scheduler.add_job(my_task, 'interval', hours=1)
scheduler.start()
性能对比实测
船长测试了100个API请求的性能对比:
**同步写法:**103秒(串行)
**异步写法(并发20):**8秒(提速12倍)
**异步写法(并发50):**4秒(提速25倍)
📌 测试环境:Python 3.11,100个模拟API(每个延迟0.5-1秒),MacBook Pro M2
常见坑与解决方案
坑1:忘记await
错误:result = fetch_data() # 这会返回协程对象
正确:result = await fetch_data() # 这才会执行并返回结果
坑2:在同步函数里调用异步函数
错误:def sync_func(): result = await async_func() # 会报错
正确:asyncio.run(async_func()) # 用run包装
坑3:忘记关闭ClientSession
用 async with 或确保 await session.close()
记住:异步不是银弹,CPU密集型任务用multiprocessing,IO密集型任务用asyncio。
总结
异步编程的核心场景:
-
批量API请求(最高频)
-
文件批量读写
-
数据库批量操作
-
定时任务调度
关键库:
-
aiohttp:异步HTTP客户端
-
aiofiles:异步文件操作
-
databases:异步数据库
-
asyncio:Python内置异步框架
学会异步,让你的Python代码"自己跑"。
作者:船长,数据分析师 + 职场观察者
微信公众号:CaptainTalk