-
一个生成器我先遍历了一遍算总数、再遍历一遍做处理,结果第二遍啥也没有、处理了零条数据:一次 Python 迭代器只能消费一次、把一次性的流当成可反复遍历的列表的深度复盘
我写脚本批量处理数据,逻辑很直白——先遍历一遍算出总共多少条打印进度,再遍历一遍真正处理每一条。本地测着没问题,上线处理大数据日志却显示共 0 条待处理、一条都没处理。打印那个变量才看清:它不是 list,而是个生成器(迭代器);迭代器只能消费一次,第一遍 sum 算总数时就把它的游标走到了尽头、消费光了,第二遍遍历时它已经空了。这篇复盘从故障现场讲到迭代器为什么只能消费一次、它和列表的本质区别(…- 0
- 0
-
我先用生成器算了个总数,再想遍历它处理数据,结果第二次遍历竟然一个元素都没有,我对着 Python 生成器只能迭代一次、用完就耗尽这个坑排查了大半天的复盘
一个让我对 Python 生成器到底是什么彻底搞明白的坑,诡异在我拿着同一个变量第一次遍历它好好的有一堆数据、第二次遍历它却空空如也一个元素都没有,就好像数据被偷偷搬空了。要先统计一批数据总数再逐个处理,用了生成器既省内存又优雅:data = (x for x in source if x.is_valid);count = sum(1 for _ in data) 算出 100 条;然后 for…- 2
- 0
-
我的 Python 函数返回的数据,第一次遍历好好的、第二次却空空如也,我对着生成器只能消费一次这个坑排查了大半天的复盘
写了个数据处理脚本,一个函数返回一批记录,调用方先遍历一遍统计总数打进度、再遍历一遍写数据库,逻辑顺得不能再顺。结果诡异:日志清清楚楚"共 5000 条",数据库里却一条都没写进去。盯着代码反复看,两次遍历代码一模一样,凭什么第一次数出 5000、第二次一条没有?甚至怀疑数据库连接,查半天没问题。排查大半天才撞上 Python 对新手极隐蔽的坑:生成器只能被消费一次。根因是函数…- 0
- 0
-
先数总数日志打着共5000条、紧接着逐条处理的循环却一条没执行数据像凭空蒸发:Python 生成器只能遍历一次的避坑复盘
这是一个数据凭空消失的诡异 bug,排查时让我一度怀疑是不是 Python 解释器出问题了。事情是这样的:我有一个处理数据的函数接收一批数据,先算一下这批数据的总数用来打日志做校验,然后再逐条地去处理它们,代码逻辑顺得不能再顺先数个数再挨个处理。可运行起来日志里明明白白打着共5000条,紧接着的逐条处理循环却一条都没执行,就好像那5000条数据在我数完个数之后开始处理之前的那一瞬间集体蒸发了。盯着…- 0
- 0
-
Python 服务内存只涨不跌:从一次 OOM 揪出几个经典内存陷阱
有个 Python 后台 worker 功能很朴素:从队列取任务、处理、写库。可它内存像潮水一样只涨不退,每隔三天就被 OOM Killer 打死,重启又从几百兆开始爬到十几个 G。加了一倍内存,只是把三天 OOM 拖成了六天。最迷惑人的是:Python 明明有垃圾回收,怎么会像 C 那样泄漏?用 tracemalloc 打出增量后真相大白:不是 GC 坏了,而是我们用几种经典写法让本该回收的对象…- 0
- 0
-
从一套用 Python 2.7 写的习惯把整张表一次性读进内存同步串行一个接一个调接口到处传裸字典靠 print 调试用 requirements.txt 锁不住依赖的祖传 ETL 脚本、核心任务 rows db.query SELECT 星 FROM orders fetchall 把整张订单表一次性全部读进内存的大列表数据量翻倍后第一次突破几千万行这条 fetchall 瞬间吃光全部内存触发 OOM Killer 进程被当场杀死且无断点续传一晚处理前功尽弃、第二天加内存重跑又撞上第二堵墙这个任务处理每一行都同步调一个外部风控接口打标几千万行就是几千万次串行一个等一个的网络请求即便单次几十毫秒累加起来也是几十个小时报表延迟大半天业务方炸锅 + 纯 Python for 循环逐元素做数值计算解释器开销巨大几百万次累加拖成几分钟想用多线程加速又撞上 GIL 更慢 + 到处传裸 dict 有哪些字段什么类型全靠脑子记拼错 order amount 成 amout 静默 KeyError 或 get 返回 None 一路带错往下 + 无任何类型注解参数传错少给字段类型不符全靠运行时炸潜伏到冷门分支凌晨才爆 + requirements.txt 加 pip freeze 锁不住传递依赖换台机器装出另一套在我机器上是好的一上生产就报谁也没见过的错 + 裸 try except pass 吞掉异常失败信息静默销毁手搓 while True 重试无上限无退避不区分该不该重试 + 满地 print 调试线上无级别无结构无法检索出问题两眼一抹黑考古整夜 → 2026 Python 3.12 现代工程体系 生成器加迭代器逐块流式处理内存占用恒定与数据总量无关 + asyncio 加 aiohttp 并发 IO 大量等待重叠几十小时压缩到分钟级 + numpy pandas 向量化底层 C 批量或 multiprocessing 绕过 GIL 真并行 + dataclass 带类型数据类字段明确拼错即报错 IDE 补全 + type hints 加 mypy 静态检查类型错误运行前揪出接进 CI + uv 加 lock 文件精确锁定整棵依赖树任何机器字节级一致 + 结构化异常加 tenacity 声明式退避重试失败可见重试有章法 + logging 结构化日志分级别可配置可检索 + pydantic-settings 集中配置 + pytest 自动回归 87 天战役复盘:47 套工程修法 + 8 个 P0 复盘 + 6 条工程哲学
5 人的数据平台团队 87 天把一套支撑公司所有数据报表的 ETL 与数据服务,从一堆用 Python 2.7 写的、习惯把整张表一次性读进内存、同步串行地一个接一个调接口、到处传裸字典、靠 print 调试、用 requirements.txt 锁不住依赖的祖传脚本,系统性地现代化到 Python 3.12 的现代工程体系——这套脚本是公司草创期一个人用几个周末写出来的,功能上一直"能…- 0
- 0
-
Python 生成器从入门到精通:yield、迭代器协议与惰性求值
很多人写了几年 Python,对 yield 的认识还停留在"它能让函数返回多个值"。这个理解不算错,但太浅,浅到没法解释这些问题:为什么 yield 的函数调用后不执行?为什么生成器只能遍历一次?生成器和迭代器到底什么关系?yield from 又是什么?这篇文章把生成器、迭代器协议、惰性求值这三件事一次讲透,并给出能直接用在生产代码里的模式。 从迭代器协议说起 要理解生成器…- 0
- 0
生成器
幸运之星正在降临...
点击领取今天的签到奖励!
恭喜!您今天获得了{{mission.data.mission.credit}}积分
我的优惠劵
-
¥优惠劵使用时效:无法使用使用时效:
之前
使用时效:永久有效优惠劵ID:×
没有优惠劵可用!







