应根据任务类型选择并发模型:cpu 密集型用 multiprocessing,i/o 密集型优先 asyncio + aiohttp 或 threading;避免 asyncio 中混用阻塞调用,须用异步替代品或 run_in_executor;合理限流、异常处理与资源清理,并复用成熟异步库。

明确任务类型再选并发模型
CPU 密集型任务(如数值计算、图像处理)适合用 multiprocessing,因为 Python 的 GIL 会严重限制多线程的并行执行能力;I/O 密集型任务(如 HTTP 请求、文件读写、数据库查询)优先考虑 asyncio + aiohttp 或 threading,其中 asyncio 在高并发 I/O 场景下资源占用更低、吞吐更高。
避免 asyncio 中混用阻塞调用
在 async 函数里直接调用 time.sleep()、requests.get() 或普通数据库驱动(如 sqlite3、psycopg2 同步版)会导致整个事件循环被阻塞。应改用:
- asyncio.sleep() 替代 time.sleep()
- aiohttp、httpx.AsyncClient 替代 requests
- aiomysql、asyncpg、aiosqlite 替代同步数据库驱动
- 必须用同步库时,用 loop.run_in_executor() 将其提交到线程池执行
合理控制并发规模,防止资源过载
不限制并发数的 asyncio.gather() 或 ThreadPoolExecutor(max_workers=None) 容易压垮服务端或耗尽本地连接/内存。建议:
- HTTP 客户端设置全局连接池限制(如 aiohttp.TCPConnector(limit=100, limit_per_host=30))
- 批量任务使用 asyncio.Semaphore 控制同时运行的协程数
- 线程池/进程池显式指定 max_workers,通常设为 CPU 核心数 × 2(I/O 密集)或 CPU 核心数(CPU 密集)
正确处理异常与生命周期
并发任务中异常容易静默丢失,资源(如连接、文件句柄)不及时释放会导致泄漏:
立即学习“Python免费学习笔记(深入)”;
- 用 async with 或 with 确保异步/同步资源自动清理
- 对 asyncio.gather() 加 return_exceptions=True,再统一检查结果中的异常对象
- 使用 asyncio.create_task() 启动后台任务时,保存 task 引用并在合适时机 await 或 cancel
- 在主程序退出前,显式 await asyncio.wait_for(shutdown(), timeout=5) 关闭异步服务
优先复用成熟异步生态,而非手动造轮子
不要从零实现连接池、重试逻辑或超时封装。直接采用:
- aiohttp 或 httpx(内置连接复用、超时、重试钩子)
- tenacity(支持 async retry decorator)
- aioredis / redis-py(>=4.2 支持 async)
- structlog + asyncio 上下文绑定做结构化日志










