恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

Python生成器实战:用yield流式处理超大文件,内存占用直降90%

  • 首页
  • 资讯中心
  • /
  • Python生成器实战:用yield流式处理超大文件,内存占用直降90%

相关资讯

AI智能体可视化监控:从Token消耗到技能进化的全链路追踪实践 2026/8/16 10:44:22
老游戏联机老是翻车?开源翻译官 IPXWrapper 让它们在 Windows 11 上重新开口 2026/8/16 10:44:22
MiniMax H3 V4 Turbo、Light2V与Bernini:AI图像生成降本增效实战指南 2026/8/16 10:44:22

最新资讯

【OC5221N 外置 MOS 降压恒流 LED 驱动芯片 聚能芯半导体一级代理】
Anomaly Transformer:融合关联先验与对偶视角的时序异常检测算法详解
5.6.3 资源争⽤死锁
群晖NAS找不到IP地址?从原理到实战的完整排查修复指南
增城区初创企业做GEO优化可以关注哪些团队
Word公式排版:用制表位实现公式居中与编号右对齐的批量设置

今日推荐

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码
【双层规划,节点出清价,绿证交易,CVaR方法】两级电力市场环境下计及风险的省间交易商最优购电模型附Matlab代码
隐式mpc+自适应mpc+时变mpc,线性时变模型预测控制附Simulink仿真

本周热门

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码
【双层规划,节点出清价,绿证交易,CVaR方法】两级电力市场环境下计及风险的省间交易商最优购电模型附Matlab代码
隐式mpc+自适应mpc+时变mpc,线性时变模型预测控制附Simulink仿真

本月精选

如何用DamaiHelper实现演唱会门票的智能自动化抢购:完整技术解决方案指南
第4篇:59 倍性能差距的索引瓶颈定位——一次教科书级的全表扫描调优
终极歌词批量下载神器:5分钟解决离线音乐库歌词同步难题

Python生成器实战:用yield流式处理超大文件,内存占用直降90%

发布时间:2026/8/16 10:44:22
Python生成器实战:用yield流式处理超大文件,内存占用直降90% 文章目录环境信息前言800MB的CSV文件直接 read 出来内存爆了一、生成器原理yield 到底做了什么二、生成器表达式一行写法的陷阱三、实战场景1流式读取大CSV四、实战场景2流式解析大JSON五、实战场景3API分页拉取六、量化验证生成器到底省了多少内存七、三个使用边界八、总结环境信息项目版本/说明Python3.10标准库csv / json / itertools无需第三方内存监控tracemalloc标准库测试场景大CSV文件 / 大JSON文件 / 分页API前言800MB的CSV文件直接 read 出来内存爆了上个月我处理香港政府开放数据平台data.gov.hk的一个交通流量数据集——800MB 的 CSV几百万行记录。我的第一版代码是这样的importcsv# ❌ 危险写法一次性把所有行读进内存withopen(traffic_flow_800mb.csv,r,encodingutf-8)asf:rowslist(csv.reader(f))# 800MB 数据全部加载进内存print(f加载了{len(rows)}行)# 然后内存就爆了——list 里存了几百万个 list 对象实际内存占用远超 800MB跑起来之后机器直接卡死。因为list(csv.reader(f))会把每一行都转换成一个 Python list 对象几百万个 list 的开销叠加起来实际内存占用是文件大小的好几倍。后来我把代码改成了生成器写法importcsv# ✅ 生成器写法逐行处理内存占用恒定defread_csv_rows(filepath):withopen(filepath,r,encodingutf-8)asf:readercsv.reader(f)forrowinreader:yieldrow# 每次只返回一行不积累fori,rowinenumerate(read_csv_rows(traffic_flow_800mb.csv)):# 处理这一行...ifi%1000000:print(f已处理{i}行)同样的功能内存占用从文件大小的数倍降到恒定的几十KB。这就是生成器的力量。收藏提示①处理大文件的第一原则——永远不要list()一个文件读取器。用yield逐行返回内存占用恒定。文末有3个开箱即用的生成器实战。一、生成器原理yield到底做了什么要理解为什么生成器省内存先理解它和普通函数、普通列表的区别。普通函数调用后一次性执行完用return返回结果然后函数就结束了。生成器函数函数体里有yield关键字。调用它不会立即执行函数体而是返回一个生成器对象。每次对这个生成器调用next()函数才执行到下一个yield处把yield后面的值吐出来然后暂停。defsimple_generator():print(开始)yield1# 第一次 next() 执行到这里返回1暂停print(继续)yield2# 第二次 next() 执行到这里返回2暂停print(结束)# 第三次 next() 会抛出 StopIterationgensimple_generator()print(next(gen))# 输出开始然后返回 1print(next(gen))# 输出继续然后返回 2print(next(gen))# 输出结束然后抛出 StopIteration关键就在于暂停这两个字。生成器不会一次性把所有值算出来存着而是用到哪个算哪个。这就是惰性求值lazy evaluation。对比一下# 列表一次性生成100万个数字全部存内存nums_list[iforiinrange(1000000)]# 内存占用约 36MB每个int对象28字节 × 100万# 生成器只是定义了一个规则不实际生成nums_gen(iforiinrange(1000000))# 内存占用约 100字节就一个生成器对象同样是 100 万个数字列表占 36MB生成器只占 100 字节。这就是内存直降 90%“的真正来源——不是魔法是不预先计算、用到才算”。二、生成器表达式一行写法的陷阱注意上面nums_gen (i for i in range(1000000))用的是圆括号这是生成器表达式。而列表推导式用的是方括号。# 列表推导式方括号—— 立即生成占内存squares_list[x*xforxinrange(1000000)]# 生成器表达式圆括号—— 惰性不占内存squares_gen(x*xforxinrange(1000000))一个常见的坑生成器表达式只能迭代一次。因为它不是存着结果而是边算边吐吐完就没了gen(x*xforxinrange(5))print(list(gen))# [0, 1, 4, 9, 16]print(list(gen))# [] —— 已经耗尽第二次是空的如果你需要多次遍历要么用列表要么用itertools.tee要么重新创建生成器。三、实战场景1流式读取大CSV回到开头的大文件场景把流式读取封装成一个可复用的生成器importcsvdefstream_csv(filepath,skip_headerTrue): 流式读取大CSV逐行yield不占内存 skip_header: 是否跳过表头行 withopen(filepath,r,encodingutf-8)asf:readercsv.DictReader(f)# DictReader 返回字典键是表头forrowinreader:yieldrow# 使用逐行处理配合条件过滤forrowinstream_csv(traffic_flow_800mb.csv):# 只处理屯门区的数据ifrow.get(district)屯門:process(row)如果还要做过滤 转换可以链式组合生成器deffilter_by_district(rows,district):过滤生成器只保留指定区forrowinrows:ifrow.get(district)district:yieldrowdefextract_columns(rows,columns):转换生成器只提取需要的列forrowinrows:yield{col:row.get(col)forcolincolumns}# 链式组合三个生成器串成流水线all_rowsstream_csv(traffic_flow_800mb.csv)tuen_mun_rowsfilter_by_district(all_rows,屯門)cleaned_rowsextract_columns(tuen_mun_rows,[time,flow,station])forrowincleaned_rows:print(row)这就是生成器流水线——每一步都是惰性的数据像水流一样从上一个生成器流到下一个全程不积累。无论文件多大内存占用恒定。四、实战场景2流式解析大JSONJSON 比 CSV 麻烦因为标准库的json.load()会把整个文件读进内存。但可以用ijson库第三方或者逐条解析 JSON Lines 格式importjsondefstream_jsonl(filepath): 流式读取 JSON Lines 格式每行一个JSON对象 香港政府部分API返回的就是这种格式 withopen(filepath,r,encodingutf-8)asf:forlineinf:lineline.strip()ifline:# 跳过空行yieldjson.loads(line)# 使用forrecordinstream_jsonl(records.jsonl):ifrecord.get(type)transaction:process(record)收藏提示②如果遇到的是单个超大 JSON 数组[{...},{...},...]标准库json.load()会全量加载。要么让数据提供方改 JSON Lines 格式要么用ijson库做增量解析。JSON Lines 是流式处理的友好格式设计数据管道时优先选它。五、实战场景3API分页拉取调用分页 API 时生成器可以优雅地隐藏分页逻辑importrequestsdeffetch_paginated(url,page_size100,max_pagesNone): 分页拉取API数据逐页yield对外表现为一个连续的流 page1whileTrue:ifmax_pagesandpagemax_pages:breakresprequests.get(url,params{page:page,size:page_size})dataresp.json()recordsdata.get(records,[])ifnotrecords:# 没有更多数据breakforrecordinrecords:yieldrecord page1# 使用调用方完全不用关心分页逻辑forrecordinfetch_paginated(https://api.data.gov.hk/v1/records):process(record)六、量化验证生成器到底省了多少内存口说无凭用tracemalloc实测一下标准库自带的内存追踪工具importtracemallocdefprocess_list(n1000000):列表方式全量加载tracemalloc.start()data[i*2foriinrange(n)]totalsum(data)current,peaktracemalloc.get_traced_memory()tracemalloc.stop()returnpeak/1024/1024# 转MBdefprocess_generator(n1000000):生成器方式惰性处理tracemalloc.start()totalsum(i*2foriinrange(n))# 注意这是生成器表达式current,peaktracemalloc.get_traced_memory()tracemalloc.stop()returnpeak/1024/1024list_mbprocess_list()gen_mbprocess_generator()print(f列表方式峰值内存:{list_mb:.1f}MB)print(f生成器方式峰值内存:{gen_mb:.1f}MB)print(f内存节省:{(1-gen_mb/list_mb)*100:.0f}%)输出示例列表方式峰值内存: 36.2 MB 生成器方式峰值内存: 0.1 MB 内存节省: 99%收藏提示③生成器不是更快而是更省内存。在CPU上生成器因为惰性调用有时反而略慢。它的核心价值是——让你能处理大到放不进内存的数据。如果数据量小到能全放内存列表反而更简单直接。七、三个使用边界生成器不是银弹有三个场景要谨慎需要随机访问生成器只能顺序迭代不能data[100]这样随机取。如果需要反复随机访问还是用列表。需要多次遍历生成器耗尽就没了。如果需要遍历两遍要么存成列表要么用itertools.tee要么重建生成器。数据量小如果数据只有几百条生成器和列表没区别反而增加了代码复杂度。大文件才值得用生成器小数据直接用列表。八、总结生成器的核心就一句话惰性求值——用到哪个算哪个不预先全部算出来。原理yield让函数暂停而不是结束配合next()逐步取值写法生成器函数yield和生成器表达式圆括号两种价值处理大文件/大JSON/分页API时内存从文件大小数倍降到恒定几十KB边界不能随机访问、只能遍历一次、小数据没必要用这篇是 Python 进阶系列的第三篇——0814 写了正则和装饰器这篇写生成器。三个主题的共同点都是写了很久 Python 但可能没真正理解的基础进阶。正则解决格式校验装饰器解决代码复用生成器解决内存瓶颈。本文为 Python 生成器技术分享。内存对比数据通过 tracemalloc 实测不同环境数值略有差异但生成器省内存的结论是确定的。香港政府数据示例为演示场景实际数据集以 data.gov.hk 为准。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号