如何读取文件的前 N ​​行?

Posted

技术标签:

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

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

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

【问题讨论】:

我可以给 n 作为命令行参数吗 【参考方案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】:

两种最直观的方法是:

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

    使用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)

【讨论】:

这实际上与decade-old top answer 相同。【参考方案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 个文件

以上是关于如何读取文件的前 N ​​行?的主要内容,如果未能解决你的问题,请参考以下文章

如何从文件中读取前 n 行和后 n 行?

linux head命令(head指令)(获取文件或管道输出结果前n行,默认前10行)与sed命令区别

linux head命令(head指令)(获取文件或管道输出结果前n行,默认前10行)与sed命令区别

html5 fileReader -- 如何只读取文件的前 N ​​个字符?

Python程序,要求打开一个文本文件,从固定行开始读取一直读取某一匹配结果的前一行

pandas读取csv文件的前几行数据(nrows参数)pandas读取csv文件的中间几行数据(skiprows=range(a,b))