内存高效地遍历大文件的一部分的方法

7 投票
1 回答
4323 浏览
提问于 2025-04-18 10:23

我通常不喜欢这样读取文件:

with open(file) as f:
    list_of_lines = f.readlines()

而是更倾向于使用这种代码。

f = open(file)
for line in file:
     #do something

除非我只需要遍历文件中的几行(而且我知道是哪几行),否则我觉得从行列表中取片段会更简单。不过现在这让我遇到了麻烦。我有一个非常大的文件(无法全部加载到内存中),但我并不需要遍历所有的行,只需要其中的几行。我已经写好了代码,可以找到我需要的第一行,并计算出之后需要编辑的行数。可是我就是不知道该怎么写这个循环。

n = #grep for number of lines 
start = #pattern match the start line 
f=open('big_file')
#some loop over f from start o start + n
      #edit lines  

编辑:我的标题可能引发了讨论,而不是给出答案。

1 个回答

14

如果我理解你的问题没错,你遇到的麻烦是把所有的文本行都存储在一个列表里,然后再取出一部分,这样会占用太多内存。你想要的是逐行读取文件,同时只关注某几行(比如说,行号在[17,34)之间的行)。

你可以试试用enumerate来跟踪你当前读取到哪一行。下面是一个基于生成器的方法,它使用yield一次只输出一行你感兴趣的内容:

def read_only_lines(f, start, finish):
    for ii,line in enumerate(f):
        if ii>=start and ii<finish:
            yield line
        elif ii>=finish:
            return

f = open("big text file.txt", "r")
for line in read_only_lines(f, 17, 34):
    print line

这个read_only_lines函数基本上是重新实现了标准库中的itertools.islice,所以你也可以用这个来做一个更简洁的实现:

from itertools import islice
for line in islice(f, 17, 34):
    print line

如果你想把感兴趣的行存储在一个列表里,而不是用生成器,只需用列表来转换它们:

from itertools import islice
lines_of_interest = list( islice(f, 17, 34) )

do_something_awesome( lines_of_interest )
do_something_else( lines_of_interest )

撰写回答