from concurrent.futures import ThreadPoolExecutor是 Python 标准库中用于简化多线程编程的模块导入语句。它提供了高级接口(如ThreadPoolExecutor)来异步执行可调用对象,自动管理线程池的创建、复用与销毁,避免手动操作threading.Thread的复杂性。
典型用法示例:
fromconcurrent.futuresimportThreadPoolExecutorimporttimedeftask(n):time.sleep(1)# 模拟I/O或耗时操作returnn**2# 使用上下文管理器自动关闭线程池withThreadPoolExecutor(max_workers=3)asexecutor:futures=[executor.submit(task,i)foriinrange(5)]results=[f.result()forfinfutures]print(results)# [0, 1, 4, 9, 16]注意事项:
- 适用于 I/O 密集型任务(如网络请求、文件读写),不适用于 CPU 密集型任务(此时应优先考虑
ProcessPoolExecutor); max_workers默认为min(32, (os.cpu_count() or 1) + 4),合理设置可避免资源争用;- 提交任务使用
submit()(返回Future对象)或map()(返回迭代器,保持顺序); - 线程安全需自行保障(如共享变量需加锁)。
ThreadPoolExecutor和ProcessPoolExecutor都属于concurrent.futures模块提供的高级并发执行器,但它们底层机制、适用场景和限制有本质区别:
✅核心区别:
| 维度 | ThreadPoolExecutor | ProcessPoolExecutor |
|---|---|---|
| 并发基础 | 基于多线程(共享同一进程的内存空间) | 基于多进程(每个进程拥有独立内存空间) |
| GIL 影响 | 受 Python 全局解释器锁(GIL)限制 →无法真正并行执行 CPU 密集型代码 | 绕过 GIL →可实现真正的并行计算(多核 CPU 利用) |
| 启动开销 | 小(线程创建/切换快) | 大(进程 fork/启动慢,需序列化参数和结果) |
| 数据共享 | 线程间可直接共享变量(需注意线程安全,如加锁) | 进程间不共享内存;参数和返回值需可序列化(pickle),通信通过 IPC(如管道) |
| 适用对象 | 适合 I/O 密集型任务(HTTP 请求、文件读写、数据库查询等) | 适合 CPU 密集型任务(数值计算、图像处理、加密解密等) |
| 异常传播 | 异常在.result()时抛出,类型保留完整 | 异常同样延迟到.result()抛出,但部分上下文(如局部栈帧)可能丢失 |
✅典型适用场景举例:
✅
ThreadPoolExecutor:- 并发发起 100 个 API 请求(
requests.get) - 批量读取多个本地小文件
- 异步日志写入或缓存刷新
- 并发发起 100 个 API 请求(
✅
ProcessPoolExecutor:- 使用 NumPy 对大型数组做矩阵乘法
- 多进程渲染图像帧(如视频转码)
- 并行训练多个轻量 ML 模型(非分布式场景)
⚠️ 注意:
ProcessPoolExecutor中的函数必须是顶层可导入的(不能是 lambda、嵌套函数或__main__中未保护的函数),否则pickle失败;- Windows 下需在
if __name__ == '__main__':保护内启动(防止递归创建进程); - 内存占用更高,频繁跨进程传递大数据(如大列表、DataFrame)会显著降低性能。
# ✅ 正确示例(CPU 密集型)fromconcurrent.futuresimportProcessPoolExecutorimportmathdefcpu_bound_task(n):returnsum(i*iforiinrange(n))if__name__=='__main__':withProcessPoolExecutor()asexecutor:results=list(executor.map(cpu_bound_task,[10**6]*4))