อ่าน N บรรทัดแรกของไฟล์ในหลาม


150

เรามีไฟล์ข้อมูลดิบขนาดใหญ่ที่เราต้องการตัดให้มีขนาดที่ระบุ ฉันมีประสบการณ์ใน. net c # อย่างไรก็ตามต้องการทำสิ่งนี้ใน python เพื่อทำให้สิ่งต่าง ๆ และเป็นที่สนใจง่ายขึ้น

ฉันจะไปเกี่ยวกับการรับ N บรรทัดแรกของไฟล์ข้อความในหลามได้อย่างไร ระบบปฏิบัติการที่ใช้จะมีผลต่อการนำไปใช้งานหรือไม่?


ฉันจะให้ n เป็นอาร์กิวเมนต์บรรทัดคำสั่ง
Nons

คำตอบ:


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 บรรทัด คุณควรวัดประสิทธิภาพเทียบกับข้อมูลทั่วไปที่คุณจะใช้กับ
John La Rooy

1
คำสั่ง with ทำงานกับ Python 2.6 และต้องการคำสั่งนำเข้าเพิ่มเติมใน 2.5 สำหรับ 2.4 หรือรุ่นก่อนหน้าคุณจะต้องเขียนโค้ดใหม่โดยลอง ... ยกเว้นบล็อค โวหารฉันต้องการตัวเลือกแรกแม้ว่าตามที่กล่าวไว้แล้วตัวที่สองจะแข็งแกร่งกว่าสำหรับไฟล์แบบสั้น
Alasdair

1
islice น่าจะเร็วกว่าที่ใช้ใน C.
Alice Purcell

22
มีในใจว่าถ้าไฟล์ที่มีน้อยแล้วสาย N นี้จะเพิ่มข้อยกเว้น StopIteration ที่คุณต้องจัดการ
อิเลียนอิลียฟ

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 นี้ได้รับการคุ้มครองในการส่งออกป้อนข้อมูลหลามกวดวิชา "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

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

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ตัวเลือกซึ่งสามารถตั้งค่าเป็น 1,000 และไม่ได้โหลดไฟล์ทั้งหมด 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 (20 พ.ย. 2552 เวลา 0:27): วิธีนี้เพิ่มส่วนหัว () และส่วนท้าย () ลงในไฟล์วัตถุ

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. ทำซ้ำในไฟล์บรรทัดต่อบรรทัดและbreakหลังNบรรทัด

  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 () รองรับส่วนต่อประสานการวนซ้ำ แจกแจง () ครอบคลุม open () และส่งกลับ tuples (ดัชนีรายการ) จากนั้นเราตรวจสอบว่าเราอยู่ในช่วงที่ยอมรับได้ (ถ้า i <LINE_COUNT) แล้วพิมพ์ผลลัพธ์

เพลิดเพลินไปกับงูหลาม ;)


[next(file) for _ in range(LINE_COUNT)]เพียงแค่นี้ก็ดูเหมือนจะเป็นทางเลือกที่ซับซ้อนมากขึ้นเล็กน้อยมาอยู่ที่
AMC


2

หากคุณต้องการสิ่งที่เห็นได้ชัด (โดยไม่ต้องค้นหาสิ่งที่เป็นความลับในคู่มือ) ทำงานโดยไม่ต้องนำเข้าและลอง / ยกเว้นและทำงานในช่วงที่เหมาะสมของ 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

หากคุณมีไฟล์ที่ใหญ่มากและสมมติว่าคุณต้องการให้เอาต์พุตเป็นอาเรย์แบบนัฟฟี่การใช้ 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

4
N คือจำนวนไบต์!
qed

5
ว้าว. พูดเกี่ยวกับการตั้งชื่อไม่ดี ชื่อฟังก์ชั่นกล่าวถึงแต่การโต้แย้งหมายถึงlines bytes
ArtOfWarfare

0

สิ่งนี้ใช้ได้สำหรับฉัน

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

ทำไมไม่ใช้ตัวจัดการบริบท ไม่ว่าในกรณีใดฉันไม่เห็นว่าการปรับปรุงนี้จะช่วยตอบคำถามที่มีอยู่มากมายได้อย่างไร
AMC

0

ใช้งานได้กับ Python 2 และ 3:

from itertools import islice

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

นี่คือความจริงเหมือนกันกับคำตอบด้านบนทศวรรษเก่า
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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.