【问题标题】:Skip first couple of lines while reading lines in Python file在读取 Python 文件中的行时跳过前几行
【发布时间】:2012-03-23 15:06:06
【问题描述】:

我想在阅读文本文件时跳过前 17 行。

假设文件如下所示:

0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
good stuff

我只想要好东西。我正在做的事情要复杂得多,但这是我遇到问题的部分。

【问题讨论】:

标签: python file lines skip


【解决方案1】:

这是前 2 个答案的 timeit 结果。请注意,“file.txt”是一个文本文件,包含 100,000+ 行随机字符串,文件大小为 1MB+。

使用迭代工具:

import itertools
from timeit import timeit

timeit("""with open("file.txt", "r") as fo:
    for line in itertools.islice(fo, 90000, None):
        line.strip()""", number=100)

>>> 1.604976346003241

使用两个 for 循环:

from timeit import timeit

timeit("""with open("file.txt", "r") as fo:
    for i in range(90000):
        next(fo)
    for j in fo:
        j.strip()""", number=100)

>>> 2.427317383000627

显然 itertools 方法在处理大文件时效率更高。

【讨论】:

    【解决方案2】:

    使用切片,如下所示:

    with open('yourfile.txt') as f:
        lines_after_17 = f.readlines()[17:]
    

    如果文件太大而无法加载到内存中:

    with open('yourfile.txt') as f:
        for _ in range(17):
            next(f)
        for line in f:
            # do stuff
    

    【讨论】:

    • 我使用第二种解决方案来读取包含 800 万 (8e6) 行的文件末尾的 10 行,大约需要 22 秒。对于如此长的文件(~250 MB),这仍然是首选(=最快)方式吗?
    • 我会使用tail
    • @wim:我猜,tail 在 Windows 上不起作用。此外,我并不总是想阅读最后 10 行。我希望能够阅读中间的一些行。 (例如,如果我在同一个文件中的 ~4e6 行之后读取 10 行,它仍然需要一半的时间,~11 秒)
    • 问题是,你需要读取行号~4e6之前的全部内容才能知道行分隔符字节在哪里,否则你不知道你已经通过了多少行。没有办法神奇地跳转到行号。 ~250 MB 应该可以将整个文件读取到内存中,这不是特别大的数据。
    • @riddleculous 请参阅stackoverflow.com/q/3346430/2491761 了解最后几行
    【解决方案3】:

    使用itertools.islice,从索引17开始。它会自动跳过前17行。

    import itertools
    with open('file.txt') as f:
        for line in itertools.islice(f, 17, None):  # start=17, stop=None
            # process lines
    

    【讨论】:

      【解决方案4】:

      如果您不想一次将整个文件读入内存,可以使用一些技巧:

      使用next(iterator),您可以前进到下一行:

      with open("filename.txt") as f:
           next(f)
           next(f)
           next(f)
           for line in f:
               print(f)
      

      当然,这有点难看,所以 itertools 有更好的方法:

      from itertools import islice
      
      with open("filename.txt") as f:
          # start at line 17 and never stop (None), until the end
          for line in islice(f, 17, None):
               print(f)
      

      【讨论】:

        【解决方案5】:

        如果是一张桌子。

        pd.read_table("path/to/file", sep="\t", index_col=0, skiprows=17)

        【讨论】:

          【解决方案6】:

          这个解决方案帮助我跳过了linetostart 变量指定的行数。 如果您也想跟踪它们,您将获得索引 (int) 和行 (string)。 在您的情况下,您将 linetostart 替换为 18,或将 18 分配给 linetostart 变量。

          f = open("file.txt", 'r')
          for i, line in enumerate(f, linetostart):
              #Your code
          

          【讨论】:

          • 这实际上不会跳过行,它只会偏移枚举计数器。
          【解决方案7】:
          for line in dropwhile(isBadLine, lines):
              # process as you see fit
          

          完整演示:

          from itertools import *
          
          def isBadLine(line):
              return line=='0'
          
          with open(...) as f:
              for line in dropwhile(isBadLine, f):
                  # process as you see fit
          

          优点:这很容易扩展到前缀行比“0”更复杂(但不相互依赖)的情况。

          【讨论】:

            【解决方案8】:

            这是一种获取文件中两个行号之间的行的方法:

            import sys
            
            def file_line(name,start=1,end=sys.maxint):
                lc=0
                with open(s) as f:
                    for line in f:
                        lc+=1
                        if lc>=start and lc<=end:
                            yield line
            
            
            s='/usr/share/dict/words'
            l1=list(file_line(s,235880))
            l2=list(file_line(s,1,10))
            print l1
            print l2
            

            输出:

            ['Zyrian\n', 'Zyryan\n', 'zythem\n', 'Zythia\n', 'zythum\n', 'Zyzomys\n', 'Zyzzogeton\n']
            ['A\n', 'a\n', 'aa\n', 'aal\n', 'aalii\n', 'aam\n', 'Aani\n', 'aardvark\n', 'aardwolf\n', 'Aaron\n']
            

            只需用一个参数调用它即可从第 n 行获取 -> EOF

            【讨论】:

              【解决方案9】:

              您可以使用 List-Comprehension 使其成为单线:

              [fl.readline() for i in xrange(17)]
              

              PEP 202Python documentation 中了解有关列表理解的更多信息。

              【讨论】:

              • 将这些行存储在一个只会被垃圾收集的列表中没有多大意义。
              • @wim:内存开销是微不足道的(并且可能是不可避免的,无论您采用哪种方式,因为您需要对这些行进行 O(n) 处理,除非您跳到文件);我只是不认为它的可读性很强。
              • 我同意@wim,如果您要丢弃结果,请使用循环。列表理解的全部意义在于您打算存储列表;你可以很容易地在一行上放置一个 for 循环。
              • 或在 0 内存双端队列中使用生成器。
              猜你喜欢
              • 2015-10-23
              • 2021-06-28
              • 2019-04-07
              • 2018-11-27
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多