【问题标题】:How to read first N lines of a file?如何读取文件的前 N ​​行?
【发布时间】:2010-12-18 13:25:24
【问题描述】:

我们有一个大的原始数据文件,我们希望将其修剪为指定的大小。

如何在 python 中获取文本文件的前 N ​​行?正在使用的操作系统会对实现产生任何影响吗?

【问题讨论】:

  • 我可以给 n 作为命令行参数吗

标签: python file head


【解决方案1】:

Python 2:

with open("datafile") as myfile:
    head = [next(myfile) for x in xrange(N)]
print head

Python 3:

with open("datafile") as myfile:
    head = [next(myfile) for x in range(N)]
print(head)

这是另一种方式(Python 2 和 3):

from itertools import islice

with open("datafile") as myfile:
    head = list(islice(myfile, N))
print(head)

【讨论】:

  • 谢谢,这确实很有帮助。两者有什么区别? (在性能、所需库、兼容性等方面)?
  • 我希望性能类似,也许第一个会稍微快一些。但是如果文件没有至少 N 行,第一个将不起作用。您最好根据将要使用的一些典型数据来衡量性能。
  • with 语句适用于 Python 2.6,在 2.5 上需要额外的 import 语句。对于 2.4 或更早版本,您需要使用 try...except 块重写代码。从风格上讲,我更喜欢第一个选项,尽管如前所述,第二个选项更适合短文件。
  • islice 可能更快,因为它是用 C 实现的。
  • 请记住,如果文件的行数少于 N 行,这将引发您必须处理的 StopIteration 异常
【解决方案2】:
N = 10
with open("file.txt", "a") as file:  # the a opens it in append mode
    for i in range(N):
        line = next(file).strip()
        print(line)

【讨论】:

  • 为什么要以追加模式打开文件?
  • @AMC 我认为这是为了不删除文件,但我们应该在这里使用'r'。
  • @Kowalski Append 模式用于添加文件,r 确实是更合乎逻辑的选择,我认为。
  • @ghostdog74,如何读取下N个值?
【解决方案3】:

如果您想快速阅读第一行并且不关心性能,可以使用.readlines(),它返回列表对象,然后对列表进行切片。

例如对于前 5 行:

with open("pathofmyfileandfileandname") as myfile:
    firstNlines=myfile.readlines()[0:5] #put here the interval you want

注意:整个文件被读取,所以从性能的角度来看不是最好的,但它 易于使用,书写速度快,易于记忆,所以如果你只想表演 一些一次性计算很方便

print firstNlines

与其他答案相比,一个优势是可以轻松选择行的范围,例如跳过前 10 行 [10:30] 或最后 10 行 [:-10] 或只取偶数行 [::2]

【讨论】:

  • 最佳答案可能更有效,但这对小文件来说就像一个魅力。
  • 请注意,这实际上是先将整个文件读入一个列表(myfile.readlines()),然后拼接它的前 5 行。
  • 应该避免这种情况。
  • 我认为没有理由使用它,它并不比更高效的解决方案更简单。
  • @AMC 感谢您的反馈,当我必须快速查看第一行时,我在控制台中使用它来探索数据,它只是节省了我编写代码的时间。
【解决方案4】:

我所做的是使用pandas 调用N 行。我认为性能不是最好的,但是例如如果N=1000

import pandas as pd
yourfile = pd.read_csv('path/to/your/file.csv',nrows=1000)

【讨论】:

  • 最好使用nrows 选项,它可以设置为1000 并且不加载整个文件。 pandas.pydata.org/pandas-docs/stable/generated/… 总的来说,pandas 对大文件有这个和其他节省内存的技术。
  • 是的,你是对的。我只是纠正它。抱歉弄错了。
  • 您可能还想添加 sep 来定义列分隔符(不应出现在非 csv 文件中)
  • @Cro-Magnon 我在文档中找不到pandas.read() 函数,您知道有关该主题的任何信息吗?
【解决方案5】:

没有特定的方法来读取文件对象公开的行数。

我想最简单的方法是:

lines =[]
with open(file_name) as f:
    lines.extend(f.readline() for i in xrange(N))

【讨论】:

  • 这是我真正想要的。虽然,我想将每一行添加到列表中。谢谢。
【解决方案6】:

两种最直观的方法是:

  1. 逐行迭代文件,breakN 行之后。

  2. 使用next() 方法N 逐行迭代文件。 (这本质上只是顶级答案的不同语法。)

代码如下:

# Method 1:
with open("fileName", "r") as f:
    counter = 0
    for line in f:
        print line
        counter += 1
        if counter == N: break

# Method 2:
with open("fileName", "r") as f:
    for i in xrange(N):
        line = f.next()
        print line

底线是,只要您不使用readlines()enumerate 将整个文件放入内存,您就有很多选择。

【讨论】:

  • 底线是,只要您不使用 readlines() 或将整个文件枚举到内存中,您就有很多选择。 不是@987654328 @懒惰?
【解决方案7】:

基于 gnibbler 最高投票答案(2009 年 11 月 20 日 0:27):此类将 head() 和 tail() 方法添加到文件对象。

class File(file):
    def head(self, lines_2find=1):
        self.seek(0)                            #Rewind file
        return [self.next() for x in xrange(lines_2find)]

    def tail(self, lines_2find=1):  
        self.seek(0, 2)                         #go to end of file
        bytes_in_file = self.tell()             
        lines_found, total_bytes_scanned = 0, 0
        while (lines_2find+1 > lines_found and
               bytes_in_file > total_bytes_scanned): 
            byte_block = min(1024, bytes_in_file-total_bytes_scanned)
            self.seek(-(byte_block+total_bytes_scanned), 2)
            total_bytes_scanned += byte_block
            lines_found += self.read(1024).count('\n')
        self.seek(-total_bytes_scanned, 2)
        line_list = list(self.readlines())
        return line_list[-lines_2find:]

用法:

f = File('path/to/file', 'r')
f.head(3)
f.tail(3)

【讨论】:

    【解决方案8】:

    我自己最方便的方式:

    LINE_COUNT = 3
    print [s for (i, s) in enumerate(open('test.txt')) if i < LINE_COUNT]
    

    基于List Comprehension的解决方案 函数 open() 支持迭代接口。 enumerate() 覆盖 open() 并返回元组(索引,项目),然后我们检查我们是否在可接受的范围内(如果 i

    享受 Python。 ;)

    【讨论】:

    • 这似乎比[next(file) for _ in range(LINE_COUNT)] 稍微复杂一些。
    【解决方案9】:

    对于前 5 行,只需执行以下操作:

    N=5
    with open("data_file", "r") as file:
        for i in range(N):
           print file.next()
    

    【讨论】:

      【解决方案10】:

      如果您想要一些显然(无需在手册中查找深奥的东西)无需导入和 try/except 且适用于相当范围的 Python 2.x 版本(2.2 到 2.6)的东西:

      def headn(file_name, n):
          """Like *x head -N command"""
          result = []
          nlines = 0
          assert n >= 1
          for line in open(file_name):
              result.append(line)
              nlines += 1
              if nlines >= n:
                  break
          return result
      
      if __name__ == "__main__":
          import sys
          rval = headn(sys.argv[1], int(sys.argv[2]))
          print rval
          print len(rval)
      

      【讨论】:

        【解决方案11】:

        如果您有一个非常大的文件,并且假设您希望输出是一个 numpy 数组,则使用 np.genfromtxt 将冻结您的计算机。根据我的经验,这要好得多:

        def load_big_file(fname,maxrows):
        '''only works for well-formed text file of space-separated doubles'''
        
        rows = []  # unknown number of lines, so use list
        
        with open(fname) as f:
            j=0        
            for line in f:
                if j==maxrows:
                    break
                else:
                    line = [float(s) for s in line.split()]
                    rows.append(np.array(line, dtype = np.double))
                    j+=1
        return np.vstack(rows)  # convert list of vectors to array
        

        【讨论】:

        • 如果你有一个非常大的文件,并假设你希望输出是一个 numpy 数组 这是一组非常独特的限制,我真的看不出任何优势在替代品上。
        【解决方案12】:

        这对我有用

        f = open("history_export.csv", "r")
        line= 5
        for x in range(line):
            a = f.readline()
            print(a)
        

        【讨论】:

        • 为什么不使用上下文管理器?无论如何,我看不出这对许多现有答案有何改进。
        【解决方案13】:

        我想通过读取整个文件来处理少于 n 行的文件

        def head(filename: str, n: int):
            try:
                with open(filename) as f:
                    head_lines = [next(f).rstrip() for x in range(n)]
            except StopIteration:
                with open(filename) as f:
                    head_lines = f.read().splitlines()
            return head_lines
        

        这要归功于 John La Rooy 和 Ilian Iliev。使用带有异常句柄的函数以获得最佳性能

        修订 1:感谢 FrankM 的反馈,我们可以进一步添加处理文件存在和读取权限

        import errno
        import os
        
        def head(filename: str, n: int):
            if not os.path.isfile(filename):
                raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), filename)  
            if not os.access(filename, os.R_OK):
                raise PermissionError(errno.EACCES, os.strerror(errno.EACCES), filename)     
           
            try:
                with open(filename) as f:
                    head_lines = [next(f).rstrip() for x in range(n)]
            except StopIteration:
                with open(filename) as f:
                    head_lines = f.read().splitlines()
            return head_lines
        

        您可以使用第二个版本,也可以使用第一个版本并稍后处理文件异常。从性能角度来看,检查速度很快,而且几乎没有问题

        【讨论】:

        • 这不是隔音的。这意味着如果出现异常,您将尝试再次读取文件,这可能会引发另一个异常。如果文件存在并且您具有读取权限,则此方法有效。如果不是,则会导致异常。接受的答案提供(解决方案 3)一个变体,它使用 islice 执行相同的操作(读取整个文件,当它的行数较少时)。但是您的解决方案比变体 1 和 2 更好。
        • 感谢@FrankM 的反馈,请看我的修改答案
        【解决方案14】:

        这是另一个不错的解决方案,list comprehension

        file = open('file.txt', 'r')
        
        lines = [next(file) for x in range(3)]  # first 3 lines will be in this list
        
        file.close()
        

        【讨论】:

          【解决方案15】:

          从 Python 2.6 开始,您可以利用 IO 基类中更复杂的函数。所以上面评分最高的答案可以改写为:

              with open("datafile") as myfile:
                 head = myfile.readlines(N)
              print head
          

          (您不必担心文件少于 N 行,因为不会引发 StopIteration 异常。)

          【讨论】:

          • 根据docs N 是要读取的字节数,不是行数
          • N 是字节数!
          • 哇。谈论糟糕的命名。函数名提到lines,但参数引用bytes
          【解决方案16】:

          这适用于 Python 2 和 3:

          from itertools import islice
          
          with open('/tmp/filename.txt') as inf:
              for line in islice(inf, N, N+M):
                  print(line)
          

          【讨论】:

          【解决方案17】:
          
          fname = input("Enter file name: ")
          num_lines = 0
          
          with open(fname, 'r') as f: #lines count
              for line in f:
                  num_lines += 1
          
          num_lines_input = int (input("Enter line numbers: "))
          
          if num_lines_input <= num_lines:
              f = open(fname, "r")
              for x in range(num_lines_input):
                  a = f.readline()
                  print(a)
          
          else:
              f = open(fname, "r")
              for x in range(num_lines_input):
                  a = f.readline()
                  print(a)
                  print("Don't have", num_lines_input, " lines print as much as you can")
          
          
          print("Total lines in the text",num_lines)
          
          

          【讨论】:

            【解决方案18】:
            #!/usr/bin/python
            
            import subprocess
            
            p = subprocess.Popen(["tail", "-n 3", "passlist"], stdout=subprocess.PIPE)
            
            output, err = p.communicate()
            
            print  output
            

            这个方法对我有用

            【讨论】:

            • 不过,这并不是真正的 Python 解决方案。
            • 我什至不明白你的答案中写了什么。请添加一些解释。
            【解决方案19】:

            使用 list(file_data)

            将您的 CSV 文件对象简单地转换为列表
            import csv;
            with open('your_csv_file.csv') as file_obj:
                file_data = csv.reader(file_obj);
                file_list = list(file_data)
                for row in file_list[:4]:
                    print(row)
            

            【讨论】:

            • 对于大文件来说会非常慢,因为您必须加载每一行才能获得前 4 个文件
            猜你喜欢
            • 2015-04-21
            • 2014-07-14
            • 2016-05-06
            • 1970-01-01
            • 2019-02-28
            • 1970-01-01
            • 2011-08-15
            • 1970-01-01
            相关资源
            最近更新 更多