Đọc N dòng đầu tiên của tệp trong python


150

Chúng tôi có một tệp dữ liệu thô lớn mà chúng tôi muốn cắt theo kích thước đã chỉ định. Tôi có kinh nghiệm về .net c #, tuy nhiên muốn làm điều này trong python để đơn giản hóa mọi thứ và không quan tâm.

Làm thế nào tôi có thể nhận được N dòng đầu tiên của một tệp văn bản trong python? Hệ điều hành đang được sử dụng có ảnh hưởng gì đến việc triển khai không?


Tôi có thể đưa ra n làm đối số dòng lệnh không
Nons 23/07/19

Câu trả lời:


240

Con trăn 2

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

Con trăn 3

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

Đây là một cách khác (cả Python 2 & 3)

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

1
Cảm ơn, điều đó thực sự rất hữu ích. Sự khác biệt giữa hai là gì? (về hiệu suất, thư viện yêu cầu, khả năng tương thích, v.v.)?
Russell

1
Tôi hy vọng hiệu suất là tương tự, có thể là lần đầu tiên sẽ nhanh hơn một chút. Nhưng cái đầu tiên sẽ không hoạt động nếu tệp không có ít nhất N dòng. Bạn tốt nhất để đo hiệu suất đối với một số dữ liệu điển hình bạn sẽ sử dụng với.
John La Rooy

1
Câu lệnh with hoạt động trên Python 2.6 và yêu cầu một câu lệnh nhập thêm vào 2.5. Đối với phiên bản 2.4 trở về trước, bạn cần viết lại mã bằng một lần thử ... ngoại trừ khối. Về mặt phong cách, tôi thích tùy chọn đầu tiên, mặc dù như đã đề cập, tùy chọn thứ hai mạnh hơn đối với các tệp ngắn.
Alasdair

1
islice có lẽ nhanh hơn khi nó được triển khai trong C.
Alice Purcell

22
Hãy nhớ rằng nếu các tệp có ít hơn thì N dòng này sẽ tăng ngoại lệ StopIteration mà bạn phải xử lý
Ilian Iliev

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
Tôi co rúm bất cứ khi nào tôi thấy f = open("file")mà không xử lý ngoại lệ để đóng tệp. Cách Pythonic để xử lý tệp là với trình quản lý bối cảnh, tức là sử dụng câu lệnh with. Điều này được đề cập trong hướng dẫn đầu vào Python đầu vào . "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."
Đánh dấu Mikofski

1
Tại sao mở tệp trong chế độ chắp thêm?
AMC

13

Nếu bạn muốn đọc những dòng đầu tiên một cách nhanh chóng và bạn không quan tâm đến hiệu suất, bạn có thể sử dụng .readlines()trả về đối tượng danh sách và sau đó cắt danh sách.

Ví dụ: 5 dòng đầu tiên:

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

Lưu ý: toàn bộ tệp được đọc vì vậy không phải là tốt nhất theo quan điểm hiệu suất nhưng nó dễ sử dụng, viết nhanh và dễ nhớ nên nếu bạn chỉ muốn thực hiện một số phép tính một lần thì rất thuận tiện

print firstNlines

Một lợi thế so với các câu trả lời khác là khả năng chọn dễ dàng phạm vi của các dòng, ví dụ bỏ qua 10 dòng đầu tiên [10:30]hoặc 10 kéo dài [:-10]hoặc chỉ lấy các dòng chẵn [::2].


2
Câu trả lời hàng đầu có lẽ là cách hiệu quả hơn, nhưng câu trả lời này hoạt động như một cơ duyên cho các tệp nhỏ.
T.Chmelevskij 7/11/2015

2
Lưu ý rằng điều này thực sự đọc toàn bộ tệp vào một danh sách trước tiên (myfile.readlines ()) và sau đó chia 5 dòng đầu tiên của nó.
AbdealiJK

2
Điều này nên tránh.
anilbey

1
Tôi thấy không có lý do để sử dụng điều này, nó không đơn giản hơn các giải pháp hiệu quả hơn nhiều.
AMC

@AMC cảm ơn bạn đã phản hồi, tôi sử dụng nó trong bảng điều khiển để khám phá dữ liệu khi tôi phải xem nhanh những dòng đầu tiên, nó chỉ giúp tôi tiết kiệm thời gian viết mã.
GM

9

Những gì tôi làm là gọi N dòng bằng cách sử dụng pandas. Tôi nghĩ hiệu suất không phải là tốt nhất, nhưng ví dụ nếu N=1000:

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

3
Tốt hơn là sử dụng nrowstùy chọn, có thể được đặt thành 1000 và toàn bộ tệp không được tải. pandas.pydata.org/pandas-docs/urdy/generated/ Từ Nói chung, gấu trúc có kỹ thuật này và các kỹ thuật tiết kiệm bộ nhớ khác cho các tệp lớn.
philshem

Vâng, bạn đúng. Tôi chỉ sửa nó. Xin lỗi vì những lỗi lầm.
Cro-Magnon

1
Bạn cũng có thể muốn thêm sepđể xác định một dấu phân cách cột (không nên xuất hiện trong tệp không phải là csv)
philshem

1
@ Cro-Magnon Tôi không thể tìm thấy pandas.read()chức năng trong tài liệu, bạn có biết bất kỳ thông tin nào về chủ đề này không?
AMC

6

Không có phương pháp cụ thể để đọc số lượng dòng được hiển thị bởi đối tượng tệp.

Tôi đoán cách dễ nhất sẽ là sau:

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

Đây là một cái gì đó tôi đã thực sự có ý định. Mặc dù, tôi mặc dù thêm từng dòng vào danh sách. Cảm ơn bạn.
artdanil

4

Dựa trên câu trả lời được bình chọn hàng đầu của gnibbler (ngày 20 tháng 11 lúc 10:27): lớp này thêm phương thức head () và tail () vào đối tượng tệp.

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:]

Sử dụng:

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

4

Hai cách trực quan nhất để làm điều này sẽ là:

  1. Lặp lại trên từng dòng tệp và breaksau Ndòng.

  2. Lặp lại trên từng dòng tệp bằng cách sử dụng thời gian next()phương thức N. (Đây thực chất chỉ là một cú pháp khác nhau cho những gì câu trả lời hàng đầu làm.)

Đây là mã:

# 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

Điểm mấu chốt là, miễn là bạn không sử dụng readlines()hoặc enumerateđưa toàn bộ tệp vào bộ nhớ, bạn có nhiều tùy chọn.


3

cách thuận tiện nhất theo cách riêng của tôi:

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

Giải pháp dựa trên mức độ hiểu danh sách Hàm open () hỗ trợ giao diện lặp. Enum Cả () bao gồm các bộ mở () và trả về (chỉ mục, mục), sau đó chúng tôi kiểm tra xem chúng tôi có nằm trong phạm vi được chấp nhận không (nếu tôi <LINE_COUNT) và sau đó chỉ cần in kết quả.

Thưởng thức Python. ;)


Điều này chỉ có vẻ như một sự thay thế phức tạp hơn một chút để [next(file) for _ in range(LINE_COUNT)].
AMC

3

Đối với 5 dòng đầu tiên, chỉ cần làm:

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

2

Nếu bạn muốn một cái gì đó rõ ràng (không cần tra cứu các công cụ bí truyền trong hướng dẫn sử dụng) mà không cần nhập và thử / ngoại trừ và hoạt động trên một loạt các phiên bản Python 2.x (2.2 đến 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

Nếu bạn có một tệp thực sự lớn và giả sử bạn muốn đầu ra là một mảng gọn gàng, sử dụng np.genfromtxt sẽ đóng băng máy tính của bạn. Điều này tốt hơn nhiều trong kinh nghiệm của tôi:

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

Nếu bạn có một tệp thực sự lớn và giả sử bạn muốn đầu ra là một mảng khó hiểu Đó là một bộ hạn chế khá độc đáo, tôi thực sự không thể thấy bất kỳ lợi thế nào đối với các lựa chọn thay thế này.
AMC

1

Bắt đầu từ Python 2.6, bạn có thể tận dụng các hàm phức tạp hơn trong clase cơ sở IO. Vì vậy, câu trả lời được xếp hạng hàng đầu ở trên có thể được viết lại thành:

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

(Bạn không phải lo lắng về việc tệp của mình có ít hơn N dòng vì không có ngoại lệ StopIteration nào bị ném.)


25
Theo tài liệu N là số byte cần đọc, không phải số dòng .
Đánh dấu Mikofski

4
N là số byte!
qed

5
Ồ Nói về việc đặt tên kém. Tên hàm đề cập linesnhưng đối số đề cập đến bytes.
ArtOfWarfare

0

Điều này làm việc cho tôi

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

Tại sao không sử dụng một trình quản lý bối cảnh? Trong mọi trường hợp, tôi không thấy điều này cải thiện như thế nào trên nhiều câu trả lời hiện có.
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

Phương pháp này hiệu quả với tôi


Đây thực sự không phải là một giải pháp Python.
AMC

Tôi thậm chí không hiểu những gì được viết trong câu trả lời của bạn. Vui lòng thêm một số lời giải thích.
Alexei Marinichenko
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.