Python'da bir dosyanın ilk N satırını okuyun


157

Belirli bir boyuta kırpmak istediğimiz büyük bir ham veri dosyamız var. .Net c # konusunda deneyimliyim, ancak işleri basitleştirmek ve ilgi dışı bırakmak için bunu python'da yapmak istiyorum.

Python'da bir metin dosyasının ilk N satırını nasıl elde edebilirim? Kullanılan işletim sisteminin uygulama üzerinde herhangi bir etkisi olacak mı?


n'yi komut satırı bağımsız değişkeni olarak verebilir miyim

Yanıtlar:


254

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)

İşte başka bir yol (hem Python 2 hem de 3)

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

1
Teşekkürler, bu gerçekten çok yardımcı oldu. İkisi arasındaki fark nedir? (performans, gerekli kitaplıklar, uyumluluk vb. açısından)?
Russell

1
Performansın benzer olmasını bekliyorum, belki de ilki biraz daha hızlı olacak. Ancak dosyada en az N satır yoksa ilki çalışmaz. Performansı birlikte kullanacağınız bazı tipik verilerle karşılaştırmak en iyisidir.
John La Rooy

1
With ifadesi Python 2.6'da çalışır ve 2.5'te fazladan bir import ifadesi gerektirir. 2.4 veya öncesi için, kodu bir try ... ile yeniden yazmanız gerekir, blok hariç. Biçimsel olarak, ilk seçeneği tercih ediyorum, ancak belirtildiği gibi ikincisi kısa dosyalar için daha sağlam.
Alasdair

1
islice muhtemelen C'de uygulandığı için daha hızlıdır
Alice Purcell

25
Dosyalarda N'den daha az satır varsa, bunun, halletmeniz gereken StopIteration istisnasını ortaya çıkaracağını unutmayın
Ilian Iliev

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

24
f = open("file")Dosyayı kapatmak için istisnasız gördüğüm her zaman utanıyorum . Pythonic dosyaları işlemenin yolu bir bağlam yöneticisidir, yani with ifadesini kullanmaktır. Bu, girdi çıktı Python öğreticisinde ele alınmıştır . "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
Dosyayı neden ekleme modunda açmalısınız?
AMC

@AMC Bence dosyayı silmek için değil, ama burada 'r' kullanmalıyız.
Kowalski

1
@Kowalski Ekleme modu dosyaya eklemek içindir r, bence daha mantıklı bir seçimdir.
AMC

14

İlk satırları hızlıca okumak istiyorsanız ve performansı önemsemiyorsanız kullanabilirsiniz. .readlines() hangi dönen liste nesnesini ve ardından listeyi dilimleyebilirsiniz.

Örneğin ilk 5 satır için:

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

Not: Tüm dosya okunduğu için performans açısından en iyisi değildir, ancak kullanımı kolaydır, yazması hızlıdır ve hatırlaması kolaydır, bu nedenle sadece bir kerelik hesaplama yapmak istiyorsanız çok uygundur

print firstNlines

Diğer cevaplarla karşılaştırıldığında bir avantaj, satır aralığını kolaylıkla seçme olanağıdır, örneğin ilk 10 satırı [10:30]veya 10'u atlamak [:-10]veya sadece çift satırları almak [::2].


2
En iyi cevap muhtemelen çok daha etkilidir, ancak bu küçük dosyalar için bir cazibe işlevi görür.
T.Chmelevskij

2
Bunun aslında tüm dosyayı önce bir listeye (myfile.readlines ()) okur ve ardından ilk 5 satırını ekler.
AbdealiJK

3
Bundan kaçınılmalıdır.
anilbey

1
Bunu kullanmak için bir neden göremiyorum, çok daha verimli çözümlerden daha basit değil.
AMC

@AMC geri bildirim için teşekkürler, ilk satırlara hızlıca bakmam gerektiğinde verileri keşfetmek için konsolda kullanıyorum, sadece kod yazarken zaman kazandırıyor.
GM

9

Yaptığım şey, kullanarak N hatlarını aramak pandas. Performansın en iyisi olmadığını düşünüyorum, ancak örneğin N=1000:

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

3
nrows1000'e ayarlanabilen ve dosyanın tamamı yüklenmeyen seçeneği kullanmak daha iyi olur . pandas.pydata.org/pandas-docs/stable/generated/… Genel olarak, pandalar büyük dosyalar için buna ve diğer bellek tasarrufu tekniklerine sahiptir.
philshem

Evet haklısın. Ben sadece düzeltiyorum. Hata için üzgünüm.
Cro-Magnon

1
Ayrıca sepbir sütun ayırıcı tanımlamak isteyebilirsiniz (csv olmayan bir dosyada
olmamalıdır

2
@ Cro-Magnon pandas.read()Dokümantasyonda işlevi bulamıyorum , konuyla ilgili herhangi bir bilgi biliyor musunuz?
AMC

6

Dosya nesnesi tarafından gösterilen satır sayısını okumak için belirli bir yöntem yoktur.

Sanırım en kolay yol şudur:

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

Bu aslında niyet ettiğim bir şeydi. Yine de, her satırı listeye eklemeyi düşünüyorum. Teşekkür ederim.
artdanil

4

Gnibbler'ın en çok oylanan cevabına göre (20 Kasım '09, 0:27): bu sınıf, dosya nesnesine head () ve tail () yöntemini ekler.

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

Kullanım:

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

4

Bunu yapmanın en sezgisel iki yolu şudur:

  1. Satır satır ve satırdan breaksonra dosya üzerinde yineleyin N.

  2. next()Yöntemi Nkez kullanarak dosya üzerinde satır satır yineleyin . (Bu aslında en iyi cevabın yaptığı şey için farklı bir sözdizimidir.)

İşte kod:

# 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

Sonuç olarak , tüm dosyayı kullanmadığınız readlines()veya enumeratebelleğe almadığınız sürece , birçok seçeneğiniz vardır.


Sonuç olarak, readlines () kullanmadığınız veya tüm dosyayı hafızaya almadığınız sürece, birçok seçeneğiniz vardır. enumerate()Tembel değil mi?
AMC

3

kendi başıma en rahat yol:

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

Liste Kavrama tabanlı çözüm open () işlevi bir yineleme arayüzünü destekler. Enumerate (), open () ve return tuple'ları (index, item) kapsar, sonra kabul edilen bir aralıkta olduğumuzu kontrol ederiz (i <LINE_COUNT ise) ve sonra sonucu yazdırırız.

Python'un keyfini çıkarın. ;)


Bu sadece biraz daha karmaşık bir alternatif gibi görünüyor [next(file) for _ in range(LINE_COUNT)].
AMC

3

İlk 5 satır için şunları yapmanız yeterlidir:

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

2

Açıkça (kılavuzlarda ezoterik şeylere bakmadan) içe aktarmadan çalışan ve denen / hariç çalışan ve makul bir Python 2.x sürümleri (2.2 ila 2.6) üzerinde çalışan bir şey istiyorsanız:

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

Gerçekten büyük bir dosyanız varsa ve çıktının uyuşmuş bir dizi olmasını istediğinizi varsayarsak, np.genfromtxt kullanmak bilgisayarınızı dondurur. Bu benim deneyimime göre çok daha iyi:

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

Gerçekten büyük bir dosyanız varsa ve çıktının uyuşuk bir dizi olmasını istediğinizi varsayarsak Bu oldukça benzersiz bir kısıtlama seti, bunun alternatiflere göre herhangi bir avantajı göremiyorum.
AMC

1

Python 2.6'dan başlayarak, GÇ temel sınıfındaki daha karmaşık işlevlerden yararlanabilirsiniz. Dolayısıyla, yukarıdaki en yüksek puan alan cevap şu şekilde yeniden yazılabilir:

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

(StopIteration istisnası atılmadığından dosyanızın N satırdan az olması konusunda endişelenmenize gerek yoktur.)


25
Dokümanlara göre N, satır sayısı değil , okunacak bayt sayısıdır .
Mark Mikofski

4
N, bayt sayısıdır!
Haz14

5
Vay. Kötü adlandırma hakkında konuşun. İşlev adından bahsediyor linesancak argüman başvuruyor bytes.
ArtOfWarfare

0

Bu benim için çalıştı

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

Neden bir bağlam yöneticisi kullanmıyorsunuz? Her halükarda, bunun birçok mevcut cevapta nasıl geliştiğini anlamıyorum.
AMC

0

Bu, Python 2 ve 3 için çalışır:

from itertools import islice

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

Bu, on yıllık en iyi cevapla neredeyse aynı .
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)


-2
#!/usr/bin/python

import subprocess

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

output, err = p.communicate()

print  output

Bu Yöntem Benim İçin Çalıştı


Yine de bu gerçekten bir Python çözümü değil.
AMC

Cevabınızda ne yazdığını bile anlamadım. Lütfen biraz açıklama ekleyin.
Alexei Marinichenko
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.