内存高效的迭代部分大文件的方法

Aja*_*jay 5 python iteration large-files

我通常会避免阅读这样的文件:

with open(file) as f:
    list_of_lines = f.readlines()
Run Code Online (Sandbox Code Playgroud)

并使用这种类型的代码.

f = open(file)
for line in file:
     #do something
Run Code Online (Sandbox Code Playgroud)

除非我只需要迭代文件中的几行(并且我知道它们是哪些行),否则它认为更容易获取list_of_lines的切片.现在这又回来咬我了.我有一个巨大的文件(无法将其读入内存)但我不需要迭代所有的行只是其中的几个.我已完成代码,找到我的第一行所在的位置,并查找需要编辑的行数.我只是不知道如何编写这个循环.

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  
Run Code Online (Sandbox Code Playgroud)

编辑:我的头衔可能导致辩论而不是答案.

Dan*_*ski 12

如果我正确理解你的问题,你遇到的问题是将所有文本行存储在列表中,然后采用切片会占用太多内存.你想要的是逐行读取文件,而忽略除了一组特定行(例如,行[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
Run Code Online (Sandbox Code Playgroud)

read_only_lines函数基本上是itertools.islice从标准库重新实现的,因此您可以使用它来实现更紧凑的实现:

from itertools import islice
for line in islice(f, 17, 34):
    print line
Run Code Online (Sandbox Code Playgroud)

如果要捕获列表而不是生成器中感兴趣的行,只需使用列表转换它们:

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

do_something_awesome( lines_of_interest )
do_something_else( lines_of_interest )
Run Code Online (Sandbox Code Playgroud)

  • 次要问题 - read_only_lines()读取整个文件,即使它已经过完了.在那里休息会很好. (2认同)