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 为准。

相关新闻

基于微信iLink API构建稳定合规的智能交互机器人实战指南

基于微信iLink API构建稳定合规的智能交互机器人实战指南

1. 项目概述:从“通知”到“交互”的进化 几年前,我还在用各种脚本往微信群里发通知,要么是依赖Web版微信的模拟登录,要么是找一些第三方封装好的库,但总逃不过一个宿命:不稳定。要么是账号被风控&#xff…

2026/10/17 1:56:10 阅读更多 →
Windows启动失败:winload.efi错误0xc000000e的完整修复指南

Windows启动失败:winload.efi错误0xc000000e的完整修复指南

1. 问题概述:当Winload.efi成为系统启动的“阿喀琉斯之踵”“无法加载操作系统,原因是关键系统驱动程序丢失或包含错误。文件:\EFI\Microsoft\Boot\winload.efi 错误代码:0xc000000e”。如果你在启动Windows 10或Windows 11时&…

2026/10/17 11:36:56 阅读更多 →
微信聊天记录导出与备份终极指南:三步把对话永久留在本地

微信聊天记录导出与备份终极指南:三步把对话永久留在本地

微信聊天记录导出与备份终极指南:三步把对话永久留在本地 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/We…

2026/10/17 1:58:58 阅读更多 →

最新新闻

MySQL 5.7.40离线安装包部署指南:glibc2.12兼容与生产级配置

MySQL 5.7.40离线安装包部署指南:glibc2.12兼容与生产级配置

简介:本资源为MySQL 5.7.40官方二进制离线安装包,专为x86_64架构、glibc 2.12及以上版本的Linux系统设计,面向数据库运维工程师、Linux系统管理员及后端开发人员,解决无外网环境下的MySQL快速部署与初始化问题。压缩包共379个文件…

2026/10/18 14:22:30 阅读更多 →
2024电赛H题自动行驶小车:MSPM0G3507+JY61P工程实现与避坑指南

2024电赛H题自动行驶小车:MSPM0G3507+JY61P工程实现与避坑指南

简介:针对2024年全国大学生电子设计竞赛H题开发的自动行驶小车完整工程源码,采用德州仪器MSPM0G3507作为主控,配合JY61P九轴姿态传感器与OLED显示模块,完整实现姿态解算、双电机差速转向和速度控制、运行状态实时显示等功能。资源…

2026/10/18 14:22:30 阅读更多 →
匿名管道实现Linux进程池:IPC并发任务分发实战

匿名管道实现Linux进程池:IPC并发任务分发实战

刚接触Linux系统编程那会儿,我被一道面试题卡了很久:如果只允许用进程,不引入额外依赖,你会怎么设计一个轻量级的并发任务分发机制?有人答共享内存加锁,有人答消息队列,其实在父子进程协同的场景…

2026/10/18 14:22:30 阅读更多 →
前端性能优化实战:从全局Loading到大数据渲染卡顿的治理方案

前端性能优化实战:从全局Loading到大数据渲染卡顿的治理方案

先别急着上虚拟列表,也别一股脑把loading都换成骨架屏。直接说结论:只要你的页面同时出现“一个全局loading转圈”和“一次性拉回几千行数据”这两件事,主线程卡顿几乎是必然的,而且根源往往不在你最先怀疑的那个环节。这不是我故…

2026/10/18 14:22:30 阅读更多 →
Vue+Node.js电子外设商城系统架构设计与实现

Vue+Node.js电子外设商城系统架构设计与实现

这个项目标题拿到手里,第一反应是"又一个商城系统",但真把它拆开看,"电子外设"这四个字才是关键。我前后做过几个商城类的项目,从图书到生鲜都碰过,电子外设这个品类在商品建模、订单流程、库存管…

2026/10/18 14:22:30 阅读更多 →
老旧ARM盒子部署可道云:Docker自建私有网盘的完整实战

老旧ARM盒子部署可道云:Docker自建私有网盘的完整实战

玩ARM盒子的人,迟早会走到“自建私有网盘”这一步。手头一台吃灰的ARM设备,刷上Armbian 5.77(Debian 9),跑在老旧内核上,想要一个能传大文件、能在线看文档、能挂到电脑上当网络硬盘的Web网盘,可…

2026/10/18 14:21:29 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →