Python多任务需按任务类型选方案:CPU密集型用multiprocessing绕过GIL,I/O密集型用threading或asyncio;asyncio是单线程协作式并发,须用await非阻塞API,multiprocessing传参需可序列化。

Python 多任务不是靠“多线程”就万事大吉的,CPU 密集型任务用 threading 基本白忙活,得换 multiprocessing 或 asyncio。
为什么 threading 在 CPU 密集场景下几乎不加速
CPython 有 GIL(全局解释器锁),同一时刻只允许一个线程执行 Python 字节码。哪怕开了 10 个 threading.Thread,算密集循环时还是串行跑。
- 典型错误现象:
time.sleep()看起来并发了,但sum(i**2 for i in range(10**7))类操作完全不提速 - 适用场景:仅适合 I/O 密集型,比如发 HTTP 请求、读写文件、数据库查询
- 参数差异:
threading.Thread(target=func, args=(x,))和multiprocessing.Process接口相似,但底层共享内存机制完全不同 - 性能影响:线程间切换开销小,但受 GIL 锁死,实际并发度 ≈ 1(CPU 密集时)
asyncio 不是“另一个多线程”,它压根不创建新线程
asyncio 是单线程内的协作式并发,靠事件循环 + await 让出控制权,本质是“把等待时间腾出来干别的”。
- 常见错误现象:在
async def函数里直接调time.sleep(2)—— 整个协程会阻塞,其他任务全卡住;必须用await asyncio.sleep(2) - 使用场景:高并发 I/O(如同时抓 100 个网页)、实时消息推送、WebSockets
- 注意点:
requests库不支持await,得换aiohttp或httpx.AsyncClient - 兼容性影响:Python 3.7+ 才推荐用
asyncio.run();低于 3.7 需手动管理事件循环
multiprocessing 能真并行,但别乱传大对象
每个进程独立内存空间,绕过 GIL,适合 CPU 密集任务,比如图像处理、数值计算、批量解析 JSON。
立即学习“Python免费学习笔记(深入)”;
- 典型错误现象:把 Pandas DataFrame、大列表或带文件句柄的对象传给
Process或Pool.map()—— 序列化失败,报PicklingError - 实操建议:
Pool比裸写Process更省心;用initializer预加载模型/配置,避免每个子进程重复初始化 - 参数差异:
Pool(processes=4)控制并发数,别设成 CPU 核数的 2 倍——可能因上下文切换反而变慢 - 性能影响:进程启动和数据序列化(
pickle)有开销,小任务用multiprocessing可能比单进程还慢
真正难的不是选哪个模块,而是判断任务类型:I/O 等待多?CPU 计算多?数据要不要共享?有没有状态依赖?这些没理清,代码写得再“标准”,运行时照样掉坑里。



















