Baca dulu N baris file dengan python

150

Kami memiliki file data mentah besar yang ingin kami pangkas ke ukuran yang ditentukan. Saya berpengalaman dalam. Net c #, namun ingin melakukan ini dengan python untuk menyederhanakan hal-hal dan tidak menarik.

Bagaimana cara saya mendapatkan N baris pertama dari file teks dengan python? Apakah OS yang digunakan akan berpengaruh pada implementasi?

Russell
sumber
dapatkah saya berikan n sebagai argumen baris perintah
Nons

Jawaban:

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)

Inilah cara lain (keduanya Python 2 & 3)

from itertools import islice
with open("datafile") as myfile:
    head = list(islice(myfile, N))
print head
John La Rooy
sumber
1
Terima kasih, itu memang sangat membantu. Apa perbedaan keduanya? (dalam hal kinerja, perpustakaan yang dibutuhkan, kompatibilitas dll)?
Russell
1
Saya berharap kinerjanya serupa, mungkin yang pertama sedikit lebih cepat. Tetapi yang pertama tidak akan berfungsi jika file tidak memiliki setidaknya N baris. Anda terbaik untuk mengukur kinerja terhadap beberapa data khas yang akan Anda gunakan.
John La Rooy
1
Pernyataan with bekerja pada Python 2.6, dan membutuhkan pernyataan impor tambahan pada 2.5. Untuk 2.4 atau lebih lama, Anda harus menulis ulang kode dengan coba ... kecuali blok. Secara gaya, saya lebih suka opsi pertama, meskipun seperti yang disebutkan yang kedua lebih kuat untuk file pendek.
Alasdair
1
Islice mungkin lebih cepat karena diimplementasikan dalam C.
Alice Purcell
22
Perlu diketahui bahwa jika file memiliki kurang dari N baris ini akan menimbulkan pengecualian StopIteration yang harus Anda tangani
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)
ghostdog74
sumber
23
Saya merasa ngeri setiap kali saya melihat f = open("file")tanpa kecuali menangani untuk menutup file. Cara Pythonic untuk menangani file adalah dengan manajer konteks, yaitu menggunakan pernyataan with. Ini tercakup dalam input input tutorial 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
1
Mengapa membuka file dalam mode tambahkan?
AMC
13

Jika Anda ingin membaca baris pertama dengan cepat dan Anda tidak peduli dengan kinerja, Anda dapat menggunakan .readlines()objek daftar pengembalian dan kemudian mengiris daftar.

Misalnya untuk 5 baris pertama:

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

Catatan: seluruh file dibaca jadi bukan yang terbaik dari sudut pandang kinerja tetapi mudah digunakan, cepat untuk menulis dan mudah diingat jadi jika Anda ingin hanya melakukan perhitungan satu kali sangat nyaman

print firstNlines

Salah satu keunggulan dibandingkan dengan jawaban lain adalah kemungkinan untuk memilih dengan mudah rentang garis misalnya melewatkan 10 baris pertama [10:30]atau 10 terakhir [:-10]atau hanya mengambil garis genap [::2].

GM
sumber
2
Jawaban teratas mungkin jauh lebih efisien, tetapi yang ini berfungsi seperti pesona untuk file kecil.
T.Chmelevskij
2
Perhatikan bahwa ini sebenarnya membaca seluruh file menjadi daftar terlebih dahulu (myfile.readlines ()) dan kemudian menyambungkan 5 baris pertama darinya.
AbdealiJK
2
Ini harus dihindari.
anilbey
1
Saya tidak melihat alasan untuk menggunakan ini, tidak ada yang lebih sederhana daripada solusi yang jauh lebih efisien.
AMC
@ AMC terima kasih atas umpan baliknya, saya menggunakannya di konsol untuk menjelajahi data ketika saya harus melihat cepat ke baris pertama, itu hanya menghemat waktu saya dalam menulis kode.
GM
9

Apa yang saya lakukan adalah memanggil saluran N menggunakan pandas. Saya pikir kinerjanya bukan yang terbaik, tetapi misalnya jika N=1000:

import pandas as pd
yourfile = pd.read('path/to/your/file.csv',nrows=1000)
Cro-Magnon
sumber
3
Lebih baik menggunakan nrowsopsi, yang dapat diatur ke 1000 dan seluruh file tidak dimuat. pandas.pydata.org/pandas-docs/stable/generated/... Secara umum, panda memiliki ini dan teknik hemat memori lainnya untuk file besar.
philshem
Ya kamu benar. Saya hanya memperbaikinya. Maaf atas kesalahannya.
Cro-Magnon
1
Anda mungkin juga ingin menambahkan sepuntuk mendefinisikan pembatas kolom (yang seharusnya tidak terjadi pada file non-csv)
philshem
1
@ Cro-Magnon Saya tidak dapat menemukan pandas.read()fungsi dalam dokumentasi, apakah Anda tahu informasi tentang subjek?
AMC
6

Tidak ada metode khusus untuk membaca jumlah baris yang diekspos oleh objek file.

Saya kira cara termudah adalah sebagai berikut:

lines =[]
with open(file_name) as f:
    lines.extend(f.readline() for i in xrange(N))
artdanil
sumber
Ini adalah sesuatu yang saya maksudkan sebenarnya. Padahal, saya menambahkan setiap baris ke daftar. Terima kasih.
artdanil
4

Berdasarkan gnibbler, jawaban pilihan teratas (20 November 2009 di 0:27): kelas ini menambahkan metode head () dan tail () ke file objek.

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

Pemakaian:

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

Dua cara paling intuitif untuk melakukan ini adalah:

  1. Iterate pada file baris demi baris, dan breaksetelah Nbaris.

  2. Iterate pada file baris demi baris menggunakan next()metode Nkali. (Ini pada dasarnya hanya sintaks yang berbeda untuk apa jawaban atas tidak.)

Ini kodenya:

# 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

Intinya adalah, selama Anda tidak menggunakan readlines()atau enumeratememasukkan seluruh file ke dalam memori, Anda memiliki banyak pilihan.

FatihAkici
sumber
3

cara yang paling nyaman sendiri:

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

Solusi berdasarkan Pemahaman Daftar Fungsi open () mendukung antarmuka iterasi. Enumerate () mencakup open () dan return tuple (index, item), lalu kami memeriksa bahwa kami berada di dalam rentang yang diterima (jika saya <LINE_COUNT) dan kemudian cukup mencetak hasilnya.

Nikmati Python. ;)

Maxim Plaksin
sumber
Ini sepertinya alternatif yang sedikit lebih rumit [next(file) for _ in range(LINE_COUNT)].
AMC
3

Untuk 5 baris pertama, cukup lakukan:

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

Jika Anda menginginkan sesuatu yang jelas (tanpa mencari hal-hal esoterik dalam manual) berfungsi tanpa impor dan coba / kecuali dan bekerja pada sejumlah versi Python 2.x (2.2 hingga 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)
John Machin
sumber
2

Jika Anda memiliki file yang sangat besar, dan dengan asumsi Anda ingin output menjadi array yang numpy, menggunakan np.genfromtxt akan membekukan komputer Anda. Ini jauh lebih baik dalam pengalaman saya:

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
cacosomoza
sumber
Jika Anda memiliki file yang sangat besar, dan dengan asumsi Anda ingin output menjadi array yang numpy Itu cukup unik pembatasan, saya tidak bisa benar-benar melihat kelebihan dari alternatif ini.
AMC
1

Mulai dari Python 2.6, Anda dapat memanfaatkan fungsi yang lebih canggih di basis IO dasar. Jadi jawaban berperingkat teratas di atas dapat ditulis ulang sebagai:

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

(Anda tidak perlu khawatir file Anda memiliki kurang dari N baris karena tidak ada pengecualian StopIteration yang dilemparkan.)

Steve Bading
sumber
25
Menurut dokumen N adalah jumlah byte untuk dibaca, bukan jumlah baris .
Mark Mikofski
4
N adalah jumlah byte!
qed
5
Wow. Bicara tentang penamaan yang buruk. Nama fungsi menyebutkan linestetapi argumen merujuk bytes.
ArtOfWarfare
0

Ini berhasil untuk saya

f = open("history_export.csv", "r")
line= 5
for x in range(line):
    a = f.readline()
    print(a)
Sukanta
sumber
Mengapa tidak menggunakan manajer konteks? Bagaimanapun, saya tidak melihat bagaimana ini meningkatkan banyak jawaban yang ada.
AMC
0

Ini berfungsi untuk Python 2 & 3:

from itertools import islice

with open('/tmp/filename.txt') as inf:
    for line in islice(inf, N, N+M):
        print(line)
sandyp
sumber
Ini hampir identik dengan jawaban teratas yang sudah berumur satu dekade .
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)
Shakirul
sumber
-1
#!/usr/bin/python

import subprocess

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

output, err = p.communicate()

print  output

Metode ini Berhasil bagi saya

Mansur Ali
sumber
Ini sebenarnya bukan solusi Python.
AMC
Saya bahkan tidak mengerti apa yang tertulis dalam jawaban Anda. Silakan tambahkan beberapa penjelasan.
Alexei Marinichenko