readlines()比for line in f更危险,因其将整个文件一次性加载为列表,内存占用与文件大小成正比;而后者基于迭代器,逐行读取、及时释放,内存稳定在kb级。

readlines() 会把整个文件所有行一次性读进内存,生成一个巨大的 list 对象——这不是“逐行处理”,而是“全量加载”,内存占用和文件大小基本成正比。
readlines() 为什么比 for line in f 更危险?
-
readlines()返回的是完整列表,哪怕你只打算遍历一次,Python 也必须先分配足够内存存下全部字符串对象(含引用、长度字段、哈希缓存等额外开销) - 一个 3GB 的纯文本日志,用
readlines()可能实际吃掉 4.5GB+ 内存(UTF-8 解码 + Python 字符串对象膨胀) - 而
for line in f底层调用的是文件迭代器,每次只从缓冲区取一行,上一行处理完后引用即被释放,内存占用稳定在几十 KB 级别
常见误用场景与后果
-
[line.strip() for line in f.readlines() if line.strip()]:先全量加载,再过滤,白占内存 -
lines = f.readlines(); process(lines[0]); process(lines[-1]):以为只用了首尾两行,其实全文件已驻留内存 - 在低配服务器(如 4GB RAM)上读 2GB 日志,
readlines()很可能触发 Linux OOM Killer 直接杀掉 Python 进程,连MemoryError都不抛
编码与换行符会让问题更隐蔽
- 文件含 BOM 或混合编码(如部分 GBK、部分 UTF-8),
readlines()可能在某一行解码失败,但此时前面几百万行早已加载进内存,无法回退 - Windows 换行符
\r\n在某些旧版 Python 中可能导致行末多出空字节,进一步增加单行对象体积
真正安全的替代不是“换一个类似函数”,而是放弃“先加载、后处理”的思维——文件对象本身就是可迭代的,for line in f 就是标准、轻量、无需额外依赖的流式入口。
容易被忽略的一点是:即使你加了 try/except 捕获 MemoryError,也来不及释放已分配的那几 GB 内存——进程往往已在崩溃边缘。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











