【问题标题】:Memory-efficent way to iterate over part of a large file迭代大文件的一部分的内存高效方法
【发布时间】:2014-06-19 16:50:46
【问题描述】:

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

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

并改用这种类型的代码。

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

除非我只需要遍历文件中的几行(并且我知道那些行),否则它认为对 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  

编辑:我的标题可能引发了一场辩论,而不是一个答案。

【问题讨论】:

  • 你所说的“#edit lines”是什么意思,对这些行做一些事情,比如将它们存储在一个列表中或将它们写入另一个文件或在大文件中修改这些行?
  • 如何找到第一行,以及之后需要编辑的行数?您必须从一开始就读取文件才能做到这一点,对吧?
  • 我将编辑文件中的行,然后将输入前后的内容打印到单独的文件中。我将只打印我更改为其他文件的行。
  • @dano 我正在使用 line = subprocess.check_output("grep 'pattern' lotsoftext.txt) 找到该信息,但我认为这不会影响答案。我在下面标记的@Dan 的答案能够帮助我。

标签: python iteration large-files


【解决方案1】:

如果我正确理解您的问题,您遇到的问题是将 所有 文本行存储在列表中,然后进行切片会占用太多内存。您想要的是逐行读取文件,同时忽略除特定行之外的所有行(例如,行[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 )

【讨论】:

  • 小问题 - read_only_lines() 读取整个文件,即使它已经完成。在那里休息会很好。
  • 好点,@tdelaney。修复它,以便生成器在该点返回。
  • @Dan 我将您的答案添加到我的代码中,它运行良好。谢谢 以前没遇到过enumerate() 很有用。谢谢!
  • 很高兴听到这个消息。请阅读itertools 和生成器表达式;它们是对大型数据结构进行“惰性迭代”的非常强大的工具。
  • python 新手常犯的一个错误是假设打开的文件在像行生成器一样使用后会自行重置。您可能应该提到islice(f,17,34) 和以后的islice(f,10,15) 将无法按预期工作,除非您调用f.seek(0) 或在实际使用第一个islice 后完全重新打开文件(generatros 可能很难理解)。
猜你喜欢
  • 2020-01-28
  • 1970-01-01
  • 2014-04-28
  • 1970-01-01
  • 1970-01-01
  • 2013-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多