当前位置: 首页 > news >正文

Python并发编程:concurrent.futures全解析

把"线程"和"进程"装进池子里,让Python并发像写同步代码一样简单


0. 为什么选concurrent.futures?

方案 易用性 自动复用 返回值 异常捕获
threading 低(手动join) 手动 易漏
multiprocessing 低(Queue) 手动 易漏
concurrent.futures ⭐⭐⭐ Future对象 统一

1. 两大池子概览

from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
池子 适用场景 并行度 开销 GIL
ThreadPoolExecutor IO密集(网络/磁盘) ≈CPU核数 低(共享内存) 受GIL
ProcessPoolExecutor CPU密集(计算) =CPU核数 高(独立解释器) 绕过GIL

2. 10行代码跑通线程池

import requests, time
from concurrent.futures import ThreadPoolExecutor, as_completedurls = [f"https://httpbin.org/delay/{i}" for i in range(1, 6)]def fetch(url):return requests.get(url, timeout=10).status_codestart = time.time()
with ThreadPoolExecutor(max_workers=5) as pool:futures = [pool.submit(fetch, u) for u in urls]for f in as_completed(futures):          # 完成顺序返回print(f.result(), time.time()-start)

vs串行:5次×1s → 并发1.2s,提速4倍|tddh


3. 核心API一图流

submit(fn, *args, **kwargs) → Future└→ future.result(timeout) / exception() / cancel()map(func, *iterables, chunksize=1) → 迭代器(按输入顺序)as_completed(futures) → 迭代器(完成顺序)

Future对象常用方法

方法 说明
result(timeout=None) 阻塞获取返回值
exception(timeout=None) 获取异常对象
cancel() 取消未运行任务
add_done_callback(fn) 完成后回调

4. 进程池演示:CPU密集

import math, time
from concurrent.futures import ProcessPoolExecutordef is_prime(n):if n < 2: return Falsefor i in range(2, int(math.sqrt(n)) + 1):if n % i == 0: return Falsereturn Truenumbers = list(range(1, 100000))start = time.time()
with ProcessPoolExecutor(max_workers=8) as pool:results = pool.map(is_prime, numbers, chunksize=1000)list(results)          # 消耗迭代器
print("ProcessPool cost:", time.time() - start)

8核MacBook:串行12s → 进程池2.1s,5.7×加速


5. 异常处理:永不遗漏

def div(a, b):return a / bwith ThreadPoolExecutor() as pool:futures = [pool.submit(div, 10, i) for i in [1, 0, 2]]for f in futures:try:print(f.result())except ZeroDivisionError as e:print("捕获异常:", e)

6. 性能调优 checklist

参数 建议值 说明
max_workers CPU核数×2(IO)/核数(CPU) 默认=min(32, os.cpu_count()+4)
chunksize 1000-10000(ProcessPool.map) 减少IPC次数
thread_name_prefix "PoolThread" 方便调试

7. 与asyncio协作

import asyncio, aiohttp
from concurrent.futures import ThreadPoolExecutordef sync_fetch(url):return requests.get(url).textasync def main():loop = asyncio.get_event_loop()with ThreadPoolExecutor() as pool:tasks = [loop.run_in_executor(pool, sync_fetch, u) for u in urls]return await asyncio.gather(*tasks)asyncio.run(main())

把阻塞函数扔进线程池,不改造源码也能享受异步!


8. 实战:多线程下载+多进程压缩

import requests, PIL.Image as Image, os
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutordef download(url):fname = url.split("/")[-1]with requests.get(url, stream=True) as r:with open(fname, "wb") as f:for chunk in r.iter_content(1024):f.write(chunk)return fnamedef thumbnail(fname, size=(128, 128)):img = Image.open(fname)img.thumbnail(size)out = "t_" + fnameimg.save(out)return out# 1. 线程池:IO密集下载
with ThreadPoolExecutor(max_workers=10) as tpool:files = list(tpool.map(download, url_list))# 2. 进程池:CPU密集压缩
with ProcessPoolExecutor() as ppool:ppool.map(thumbnail, files)

8核实测:100张4MB图片 → 下载30s+压缩15s,并行后总耗时35s


9. 常见坑与解决

现象 解决
进程池pickle失败 lambda/局部函数 定义在模块顶层
线程池GIL阻塞 CPU任务无加速 换ProcessPool
忘记消耗迭代器 map返回生成器 list()或for循环
取消已运行任务 cancel()返回False 判断future.running()

10. 总结:一张思维导图

并发任务
├─ IO密集 → ThreadPoolExecutor
├─ CPU密集 → ProcessPoolExecutor
├─ 异步协程 → asyncio.run_in_executor
└─ 性能调优 → chunksize+max_workers

记住:先池化,再异步,最后量化验证——让并发变成一件优雅的事!

http://www.gsyq.cn/news/66642.html

相关文章:

  • 一题多解的题目
  • 在 vscode 中部署juypter notebook 插件
  • PostgreSQL性能调优:应对表膨胀、索引碎片和无效索引问题
  • C#集合及其操作
  • IL2CPP逆向
  • ubuntu学习笔记1.文件权限
  • 20232312 2025-2026-1 《网络与系统攻防技术》实验七实验报告
  • 20232424 2025-2026-1 《网络与系统攻防技术》实验七实验报告
  • FastAPI(TortoiseORM+Aerich)和Flask(sqlalchemy+Migrate)数据库持久化
  • 2025年长春笔记本电脑售后维修点推荐:联想华硕戴尔等品牌哪家更靠谱?全方位评测与用户口碑解析
  • 详细介绍:汽车尾气检测的 “黄金标准”:HORIBA MEXA-584L 全功能汽车排放废气分析仪技术解析
  • 【人工智能数学基础】什么是高斯分布/正态分布? - 教程
  • 实验心得
  • 为什么硬盘的容量宣传与实际不一致?
  • 2025年南京笔记本电脑售后维修点推荐:哪个性价比最高?多品牌维修点对比与选购指南
  • 【ABC135F】Strings of Eternity
  • 2025年南通笔记本售后点推荐:三星戴尔联想等品牌哪家性价比最高?深度解析与选择对比
  • C++ 非模板的右值引用
  • 2025年重庆笔记本电脑售后维修点推荐:联想华硕戴尔等品牌哪家强?多维度实测与用户口碑解析
  • 2025年郑州笔记本电脑维修点推荐:联想华硕戴尔等品牌哪家服务更优?全方位评测与口碑分析
  • 题解:P14620 [2019 KAIST RUN Fall] Minimum Diameter Spanning Tree
  • 飞牛OS挂载外接存储到我的文件
  • 11月30日总结 - 作业----
  • 告别频繁更换:Nordic nPM2100 PMIC 助力开发人员提升非充电电池项目设计
  • 787878[GESP202409 二级] 数位之和
  • 2025-12-02-Nature 本周最新文献速递
  • 四、Java方法
  • 英氏辅食有问题吗?答案在这里
  • 挑战Ceph的“霸权”?RustFS的优劣势深度剖析
  • 高中物理网课老师选择指南:适配基础到拔高的全阶段需求