it-swarm.com.de

Nur bestimmte Zeilen lesen

Ich verwende eine for-Schleife, um eine Datei zu lesen, aber ich möchte nur bestimmte Zeilen lesen, z. B. Zeile 26 und 30. Gibt es eine integrierte Funktion, um dies zu erreichen?

Vielen Dank

161
3zzy

Wenn die zu lesende Datei groß ist und Sie nicht die gesamte Datei gleichzeitig lesen möchten:

fp = open("file")
for i, line in enumerate(fp):
    if i == 25:
        # 26th line
    Elif i == 29:
        # 30th line
    Elif i > 29:
        break
fp.close()

Beachten Sie diesen i == n-1 für die nth-Zeile.


In Python 2.6 oder höher:

with open("file") as fp:
    for i, line in enumerate(fp):
        if i == 25:
            # 26th line
        Elif i == 29:
            # 30th line
        Elif i > 29:
            break
213
Alok Singhal

Die schnelle Antwort:

f=open('filename')
lines=f.readlines()
print lines[25]
print lines[29]

oder:

lines=[25, 29]
i=0
f=open('filename')
for line in f:
    if i in lines:
        print i
    i+=1

Es gibt eine elegantere Lösung zum Extrahieren vieler Zeilen: linecache (mit freundlicher Genehmigung von "python: Wie springt man zu einer bestimmten Zeile in einer großen Textdatei?" , einer vorherigen stackoverflow.com-Frage).

Zitieren der oben verlinkten Python-Dokumentation:

>>> import linecache
>>> linecache.getline('/etc/passwd', 4)
'sys:x:3:3:sys:/dev:/bin/sh\n'

Ändern Sie den 4 in die gewünschte Zeilennummer und Sie sind eingeschaltet. Beachten Sie, dass 4 die fünfte Zeile bringen würde, da die Zählung auf Null basiert.

Wenn die Datei möglicherweise sehr groß ist und beim Einlesen in den Speicher Probleme verursacht, ist es möglicherweise ratsam, die Anweisungen von @ Alok zu übernehmen und enumerate () zu verwenden.

Schlussfolgern:

  • Verwenden Sie fileobject.readlines() oder for line in fileobject als schnelle Lösung für kleine Dateien. 
  • Verwenden Sie linecache für eine elegantere Lösung, die zum Lesen vieler Dateien recht schnell möglich ist, immer wieder möglich.
  • Nehmen Sie @ Aloks Rat und verwenden Sie enumerate() für Dateien, die sehr groß sein könnten und nicht in den Speicher passen. Beachten Sie, dass sich diese Methode möglicherweise verlangsamt, weil die Datei sequentiell gelesen wird.
129
Adam Matan

Ein schneller und kompakter Ansatz könnte sein:

def picklines(thefile, whatlines):
  return [x for i, x in enumerate(thefile) if i in whatlines]

dies akzeptiert jedes offene dateiähnliche Objekt thefile (es bleibt dem Aufrufer überlassen, ob es von einer Festplattendatei oder über einen Socket oder einen anderen dateiähnlichen Stream geöffnet werden soll) und einen Satz von nullbasierten Zeilenindizes whatlines und gibt eine Liste mit wenig Speicherplatz und angemessener Geschwindigkeit zurück. Wenn die Anzahl der zurückgegebenen Zeilen sehr groß ist, können Sie einen Generator bevorzugen:

def yieldlines(thefile, whatlines):
  return (x for i, x in enumerate(thefile) if i in whatlines)

dies ist im Grunde nur für Schleifen geeignet - beachten Sie, dass der einzige Unterschied darin besteht, dass in der return-Anweisung abgerundete anstelle von eckigen Klammern verwendet werden, was ein Listenverständnis und einen Generatorausdruck bewirkt.

Beachten Sie weiterhin, dass trotz der Erwähnung von "Zeilen" und "Datei" diese Funktionen viel sind, viel allgemeiner - sie funktionieren auf any iterable, sei es eine geöffnete Datei oder eine andere, die zurückkehren eine Liste (oder einen Generator) von Artikeln basierend auf ihren fortlaufenden Artikelnummern. Ich würde also vorschlagen, passendere allgemeine Namen zu verwenden ;-).

25
Alex Martelli

Um eine andere Lösung anzubieten:

import linecache
linecache.getline('Sample.txt', Number_of_Line)

Ich hoffe das geht schnell und einfach :)

25
KingMak

wenn Sie Zeile 7 wünschen

 line = open ("file.txt", "r"). readlines () [7] 
12
MadSc13ntist

Der Vollständigkeit halber gibt es noch eine weitere Option.

Beginnen wir mit einer Definition aus python docs :

slice Ein Objekt, das normalerweise einen Teil einer Sequenz enthält. Ein Slice wird mit der Indexnotation [] mit Doppelpunkten zwischen Zahlen erstellt, wenn mehrere angegeben werden, z. B. in Variablenname [1: 3: 5]. Die Klammer- (Index-) Notation verwendet intern Slice-Objekte (oder in älteren Versionen __getslice __ () und __setslice __ ()).

Obwohl die Slice-Notation im Allgemeinen nicht direkt auf Iteratoren anwendbar ist, enthält das itertools-Paket eine Ersetzungsfunktion:

from itertools import islice

# print the 100th line
with open('the_file') as lines:
    for line in islice(lines, 99, 100):
        print line

# print each third line until 100
with open('the_file') as lines:
    for line in islice(lines, 0, 100, 3):
        print line

Der zusätzliche Vorteil der Funktion ist, dass der Iterator erst am Ende gelesen wird. So können Sie komplexere Dinge tun:

with open('the_file') as lines:
    # print the first 100 lines
    for line in islice(lines, 100):
        print line

    # then skip the next 5
    for line in islice(lines, 5):
        pass

    # print the rest
    for line in lines:
        print line

Und um die ursprüngliche Frage zu beantworten:

# how to read lines #26 and #30
In [365]: list(islice(xrange(1,100), 25, 30, 4))
Out[365]: [26, 30]
9
newtover

Das Lesen von Dateien ist unglaublich schnell. Das Lesen einer 100-MB-Datei dauert weniger als 0,1 Sekunden (siehe meinen Artikel Lesen und Schreiben von Dateien mit Python ). Daher sollten Sie es vollständig lesen und dann mit den einzelnen Zeilen arbeiten.

Was die meisten Antworten hier tun, ist nicht falsch, sondern schlechter Stil. Das Öffnen von Dateien sollte immer mit with erfolgen, da dadurch sichergestellt wird, dass die Datei wieder geschlossen wird.

Also solltest du es so machen:

with open("path/to/file.txt") as f:
    lines = f.readlines()
print(lines[26])  # or whatever you want to do with this line
print(lines[30])  # or whatever you want to do with this line

Riesige Dateien

Wenn Sie eine große Datei haben und der Speicherbedarf ein Problem ist, können Sie sie zeilenweise verarbeiten:

with open("path/to/file.txt") as f:
    for i, line in enumerate(f):
        pass  # process line i
5
Martin Thoma

Einige davon sind schön, aber es geht viel einfacher:

start = 0 # some starting index
end = 5000 # some ending index
filename = 'test.txt' # some file we want to use

with open(filename) as fh:
    data = fin.readlines()[start:end]

print(data)

Dazu wird einfach Listenaufteilung verwendet, die gesamte Datei wird geladen, aber die meisten Systeme minimieren den Speicherbedarf entsprechend. Sie sind schneller als die meisten der oben genannten Methoden und funktionieren mit meinen 10G + -Datendateien. Viel Glück!

4
Will

Sie können einen seek () - Aufruf ausführen, der Ihren Lesekopf auf ein bestimmtes Byte in der Datei positioniert. Dies hilft Ihnen nicht, wenn Sie nicht genau wissen, wie viele Bytes (Zeichen) vor der Zeile, die Sie lesen möchten, in die Datei geschrieben werden. Vielleicht ist Ihre Datei streng formatiert (jede Zeile ist X-Byte-Anzahl?) Oder Sie können die Anzahl der Zeichen selbst zählen (denken Sie daran, unsichtbare Zeichen wie Zeilenumbrüche einzufügen), wenn Sie die Geschwindigkeit wirklich erhöhen möchten. 

Ansonsten müssen Sie jede Zeile vor der gewünschten Zeile lesen, wie in einer der vielen Lösungen, die bereits vorgeschlagen wurden.

3
Roman

Wie wäre es damit:

>>> with open('a', 'r') as fin: lines = fin.readlines()
>>> for i, line in enumerate(lines):
      if i > 30: break
      if i == 26: dox()
      if i == 30: doy()
2
Hamish Grubijan

Eine bessere und geringfügige Änderung für Alok Singhals Antwort

fp = open("file")
for i, line in enumerate(fp,1):
    if i == 26:
        # 26th line
    Elif i == 30:
        # 30th line
    Elif i > 30:
        break
fp.close()
2
sedic

Ich bevorzuge diesen Ansatz, weil er allgemeiner ist, d. H. Sie können ihn für eine Datei, für das Ergebnis von f.readlines(), für ein StringIO-Objekt verwenden.

def read_specific_lines(file, lines_to_read):
   """file is any iterable; lines_to_read is an iterable containing int values"""
   lines = set(lines_to_read)
   last = max(lines)
   for n, line in enumerate(file):
      if n + 1 in lines:
          yield line
      if n + 1 > last:
          return

>>> with open(r'c:\temp\words.txt') as f:
        [s for s in read_specific_lines(f, [1, 2, 3, 1000])]
['A\n', 'a\n', 'aa\n', 'accordant\n']
2
Robert Rossney

Wenn es Ihnen nichts ausmacht zu importieren, dann tut fileinput genau das, was Sie brauchen (das ist, Sie können die Zeilennummer der aktuellen Zeile lesen)

2
ennuikiller
def getitems(iterable, items):
  items = list(items) # get a list from any iterable and make our own copy
                      # since we modify it
  if items:
    items.sort()
    for n, v in enumerate(iterable):
      if n == items[0]:
        yield v
        items.pop(0)
        if not items:
          break

print list(getitems(open("/usr/share/dict/words"), [25, 29]))
# ['Abelson\n', 'Abernathy\n']
# note that index 25 is the 26th item
2
Roger Pate

Hier sind meine kleinen 2 Cent, was es wert ist;)

def indexLines(filename, lines=[2,4,6,8,10,12,3,5,7,1]):
    fp   = open(filename, "r")
    src  = fp.readlines()
    data = [(index, line) for index, line in enumerate(src) if index in lines]
    fp.close()
    return data


# Usage below
filename = "C:\\Your\\Path\\And\\Filename.txt"
for line in indexLines(filename): # using default list, specify your own list of lines otherwise
    print "Line: %s\nData: %s\n" % (line[0], line[1])
2
AWainb
file = '/path/to/file_to_be_read.txt'
with open(file) as f:
    print f.readlines()[26]
    print f.readlines()[30]

Mit der with-Anweisung wird die Datei geöffnet, die Zeilen 26 und 30 gedruckt und die Datei geschlossen. Einfach!

1
user3901273

Dateiobjekte haben eine .readlines () -Methode, mit der Sie eine Liste des Inhalts der Datei erhalten, eine Zeile pro Listenelement. Danach können Sie normale Listenschneideverfahren verwenden.

http://docs.python.org/library/stdtypes.html#file.readlines

1
Josh Wright

Sie können dies sehr einfach mit dieser von jemandem bereits erwähnten Syntax tun, aber es ist bei weitem der einfachste Weg, dies zu tun:

inputFile = open("lineNumbers.txt", "r")
lines = inputFile.readlines()
print (lines[0])
print (lines[2])
1
Trey50Daniel

Um Zeile 3 zu drucken, 

line_number = 3

with open(filename,"r") as file:
current_line = 1
for line in file:
    if current_line == line_number:
        print(file.readline())
        break
    current_line += 1

Ursprünglicher Autor: Frank Hofmann

1
crazy_daffodils

@OP können Sie Aufzählung verwenden

for n,line in enumerate(open("file")):
    if n+1 in [26,30]: # or n in [25,29] 
       print line.rstrip()
1
ghostdog74

Wenn Ihre große Textdatei file streng strukturiert ist (dh jede Zeile hat die gleiche Länge l), können Sie sie für n- te Zeile verwenden

with open(file) as f:
    f.seek(n*l)
    line = f.readline()  # please notice the s at the end!
    last_pos = f.tell()

Haftungsausschluss Dies funktioniert nur bei Dateien gleicher Länge!

1
Michael Dorner

Gewünschte Zeile drucken . Zeile über/unter der gewünschten Zeile drucken.

def dline(file,no,add_sub=0):
    tf=open(file)
    for sno,line in enumerate(tf):
        if sno==no-1+add_sub:
         print(line)
    tf.close()

führen Sie ----> dline aus ("D:\dummy.txt", 6) dh dline ("Dateipfad", Zeilennummer, wenn Sie möchten, dass die obere Zeile der gesuchten Zeile 1 für unteres -1 ergibt, ist dies ein optionaler Standardwert genommen werden 0)

0
sudhir tataraju

Ziemlich schnell und auf den Punkt.

So drucken Sie bestimmte Zeilen in einer Textdatei. Erstellen Sie eine "lines2print" -Liste und dann Drucken Sie einfach, wenn die Aufzählung "in" der lines2print-Liste ist . Um zusätzliche '\ n' zu entfernen, verwenden Sie line.strip () oder line.strip ('\ n ') . Ich mag "Listenverständnis" und versuche es zu verwenden, wenn ich . Ich mag die "with" -Methode, um Textdateien zu lesen, um zu verhindern, dass Eine Datei aus irgendeinem Grund offen bleibt.

lines2print = [26,30] # can be a big list and order doesn't matter.

with open("filepath", 'r') as fp:
    [print(x.strip()) for ei,x in enumerate(fp) if ei in lines2print]

oder wenn die Liste klein ist, geben Sie einfach die Liste als Liste in das Verständnis ein.

with open("filepath", 'r') as fp:
    [print(x.strip()) for ei,x in enumerate(fp) if ei in [26,30]]
0
Mike Adrion