python处理10gb大文件应采用流式按行读取+分块写入,禁用readlines()或read()以防oom;for line in f内存稳定在kb级,按行数切分(如每50万行)更常用且安全,避免seek()切坏行。

用 open() 按行读 + 分块写,别加载进内存
10GB 文件不能用 readlines() 或 read() 一次性读入,会直接 OOM。核心是流式处理:打开一次源文件,逐行迭代,边读边分发到目标小文件中。Python 的 for line in f: 默认就是缓冲读取,内存占用稳定在几 KB 级别,这是最安全的起点。
常见错误是试图用 file.seek() 随机跳转分片——文本文件没有固定行长,seek() 到字节位置无法保证停在行首,极易切坏一行。除非你事先建好行偏移索引,否则别碰 seek()。
实操建议:
- 用
with open(src, "r", encoding="utf-8") as f:显式指定编码,避免解码失败中断 - 每写满 N 行(比如 10 万行)就关闭当前输出文件、打开下一个,避免单文件过大或句柄泄漏
- 用
enumerate()计行号比自己维护计数器更可靠,尤其遇到空行或 \r\n 混用时
按行数切分 vs 按字节数切分,选哪个?
按行数切分(如每 50 万行一个文件)最常用,语义清晰、下游易处理,但单个文件大小不均——有长日志行的文件可能远超预期体积;按字节数切分(如每 100MB 一个文件)能严格控体积,但必须确保不切断行:读到接近阈值时,继续读直到遇到换行符再切。
性能差异不大,但兼容性上行数法更稳。Windows 和 Linux 换行符不同(\r\n vs \n),用 line.rstrip('\r\n') 清理比正则快得多。
关键参数差异:
-
chunk_size_lines = 500000:推荐 10 万~100 万之间,太小导致频繁 IO,太大降低并行潜力 -
chunk_size_bytes = 100 * 1024 * 1024:若选字节法,预留 1–2KB 缓冲区防止临界点卡死 - 不要用
os.path.getsize()做实时判断——它返回的是初始大小,写入过程中文件增长会导致计算漂移
多进程加速真的有用吗?
纯 CPU 密集型任务(如每行做 JSON 解析)上多进程有意义;但对“读一行 → 写一行”这种 IO 密集型操作,多进程反而因磁盘争抢变慢,尤其机械硬盘。SSD 上提升也有限,因为 Python 的 GIL 在 IO 时已释放,单进程已能跑满磁盘吞吐。
真正有效的加速点是:用 buffering=8192 调大缓冲区,或把输出文件挂到 tmpfs(内存盘)再 mv 回磁盘——这比开 4 个进程实在得多。
如果坚持多进程,注意:
- 别用
multiprocessing.Pool直接传文件对象——文件句柄不能跨进程序列化 - 改用
concurrent.futures.ProcessPoolExecutor+ 每个子进程独立打开源文件,靠偏移量划分读取区间(需预扫描换行符位置) - Windows 下必须把主逻辑包进
if __name__ == "__main__":,否则 spawn 失败
如何避免写一半崩溃后重头来过?
10GB 文件拆分耗时可能几十分钟,中途断电或 Ctrl+C 会导致部分输出文件不完整。最轻量的容错方案是:先写临时文件(如 part_001.tmp),写完用 os.replace() 原子重命名。这样即使中断,也不会留下半截的有效文件干扰后续逻辑。
更进一步可记录 checkpoint:每次写满一个 chunk 后,在单独的 progress.log 里追加一行 part_003,624812(表示第 3 个文件已写到第 624812 行)。恢复时跳过已存在的文件,从对应行继续读。
容易被忽略的细节:
-
print()默认行缓冲,重定向到文件时可能不及时刷盘,务必在写入关键状态后调用sys.stdout.flush() - 某些 NFS 或网络存储对原子重命名支持不全,
os.replace()可能退化为 copy+delete,要提前验证 - 别依赖
time.time()命名文件——秒级精度不够,用datetime.now().strftime("%Y%m%d_%H%M%S_%f")[:-3]更稳妥
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











