Python itertools.product处理大文件时如何避免全量加载入内存
问题根因
程序无响应的核心原因是itertools.product的实现逻辑不支持惰性迭代传入的可迭代对象:它在正式执行组合逻辑前,会把所有传入的可迭代对象全部转换成元组缓存到内存中。哪怕你传入的是支持逐行读取的文件句柄,它也会先把两个文件的所有内容全部读完、存在内存里,才会开始做行内容的配对计算。
小文件测试时全量读取速度快,所以能很快进入后续逻辑出结果;换成大文件后,全量读文件+缓存内容的阶段会耗时极长,甚至直接占满内存触发系统卡顿,表现出来就是程序无响应。
零内存溢出解决方案
不需要依赖itertools.product,手动实现两层遍历即可,全程内存中只会保留当前正在处理的2行内容,内存占用恒定,和文件总体积无关,不会出现大文件撑爆内存的问题:
import time # 外层逐行遍历第一个文件,每次仅在内存中保留当前行 with open('text1.txt', 'r', encoding='utf-8') as f1: for line1 in f1: t1 = line1.strip() # 每拿到一个第一文件的行,就重新打开第二个文件逐行配对 with open('text2.txt', 'r', encoding='utf-8') as f2: for line2 in f2: t2 = line2.strip() combined = t1 + t2 time.sleep(1) print(combined)
这个方案的缺点是第二个文件会被重复打开遍历,重复次数等于第一个文件的总行数,磁盘IO开销相对更高。
效率优化方案
如果两个文件体积差距较大,可以把体积更小的文件一次性读入内存缓存,大文件保持逐行遍历,既可以控制内存占用在可接受范围,又能大幅减少重复读大文件的IO开销,运行速度会明显提升:
import time # 提前把体积更小的文件读入内存做预处理,内存占用可控 with open('text2.txt', 'r', encoding='utf-8') as f2: cached_lines = [line.strip() for line in f2] # 外层逐行遍历超大文件,内存始终仅保留当前处理的行 with open('text1.txt', 'r', encoding='utf-8') as f1: for line1 in f1: t1 = line1.strip() for t2 in cached_lines: combined = t1 + t2 time.sleep(1) print(combined)
调整规则很简单:哪个文件体积小,就把哪个文件提前缓存到内存,大文件放在外层逐行遍历即可。
内容的提问来源于stack exchange,提问作者deway54
相关产品推荐
相关产品推荐

