在python中读取文件的前N行


150

我们有一个很大的原始数据文件,我们希望将其修剪到指定的大小。我在.net c#方面经验丰富,但是想在python中做到这一点,以简化事情,并且不感兴趣。

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


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

Answers:


240

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

1
谢谢,这确实很有帮助。两者有什么区别?(在性能,所需的库,兼容性等方面)?
罗素

1
我希望性能类似,也许第一个会更快。但是,如果文件没有至少N行,第一个将不起作用。最好根据将要使用的一些典型数据来衡量性能。
约翰·拉鲁伊

1
with语句在Python 2.6上有效,并且在2.5上需要额外的import语句。对于2.4或更早版本,您需要使用try ... except块重写代码。从风格上讲,我更喜欢第一个选项,尽管如上所述,第二个选项对于短文件更为健壮。
阿拉斯戴尔

1
islice是可能更快,因为它是用C实现的
爱丽丝赛尔

22
请记住,如果文件少于N行,这将引发您必须处理的StopIteration异常
Ilian Iliev 2012年

19
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)

23
每当我看到f = open("file")无例外地关闭文件时,我都会畏缩。处理文件的Pythonic方法是使用上下文管理器,即使用with语句。输入输出Python教程对此进行了介绍。"It is good practice to use the with keyword when dealing with file objects. This has the advantage that the file is properly closed after its suite finishes, even if an exception is raised on the way."
Mark Mikofski 2013年

1
为什么以追加模式打开文件?
AMC

13

如果您想快速阅读第一行而又不关心性能,则可以使用.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]


2
最佳答案可能会更有效率,但是这个答案就像小文件的魅力一样。
T.Chmelevskij 2015年

2
请注意,这实际上首先将整个文件读入列表(myfile.readlines()),然后将其前5行拼接起来。
AbdealiJK

2
应该避免这种情况。
anilbey

1
我认为没有理由使用它,没有比高效得多的解决方案更简单的了。
AMC

@AMC感谢您的反馈,当我不得不快速浏览第一行时,我在控制台中使用它来浏览数据,这只是节省了我编写代码的时间。
GM

9

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

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

3
最好使用该nrows选项,该选项可以设置为1000并且不加载整个文件。pandas.pydata.org/pandas-docs/stable/generated/…通常,pandas具有针对大文件的这种和其他节省内存的技术。
philshem

是的,你是对的。我只是纠正它。对不起,这个错误。
Cro-Magnon

1
您可能还需要添加sep以定义列定界符(在非csv文件中不应出现)
philshem

1
@ Cro-Magnon我pandas.read()在文档中找不到该功能,您知道有关此主题的任何信息吗?
AMC

6

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

我想最简单的方法如下:

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

这是我真正想要的。虽然,我虽然将每一行添加到列表中。谢谢。
artdanil

4

基于gnibbler最高投票的答案(09年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)

4

做到这一点的两种最直观的方法是:

  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将其放入内存中,您就有很多选择。


3

我自己最方便的方法:

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

基于列表理解的解决方案 的函数open()支持迭代接口。enumerate()覆盖open()并返回元组(索引,项目),然后我们检查是否在可接受的范围内(如果i <LINE_COUNT),然后简单地打印结果。

享受Python。;)


这似乎是的更复杂的选择[next(file) for _ in range(LINE_COUNT)]
AMC

3

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

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

2

如果您希望某些东西(无需查找手册中深奥的东西)显然不需要导入和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)

2

如果文件很大,并且假设您希望输出为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数组,那是一组非常独特的限制,与其他方法相比,我看不出有什么优势。
AMC

1

从Python 2.6开始,您可以在IO基本类中利用更复杂的功能。因此,上面评分最高的答案可以重写为:

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

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


25
根据文档 N是数个字节来读取,数量线
Mark Mikofski 2013年

4
N是字节数!
2014年

5
哇。谈论糟糕的命名。函数名称提及,lines但参数提及bytes
ArtOfWarfare 2015年

0

这对我有用

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

为什么不使用上下文管理器?无论如何,我看不出在许多现有答案上有何改进。
AMC


0

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)

-1
#!/usr/bin/python

import subprocess

p = subprocess.Popen(["tail", "-n 3", "passlist"], stdout=subprocess.PIPE)

output, err = p.communicate()

print  output

这种方法对我有用


不过,这实际上不是Python解决方案。
AMC

我什至不明白你的答案写的是什么。请添加一些说明。
Alexei Marinichenko
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.