HOWTO · Python

Wie man bestimmte Zeilen aus einer Datei in Python liest

Mit `readlines()` lassen sich kleine Dateien lesen; für große Dateien eignet sich `enumerate()` zum schrittweisen Durchlaufen. `linecache` unterstützt wiederholte Zeilenzugriffe auf dieselbe Datei und speichert Dateiinhalte im Cache, was Speicher benötigt.

Auf dieser Seite

Um eine oder mehrere bestimmte Zeilen aus einer Python-Textdatei zu lesen, entscheiden Sie zuerst, ob die Zeilennummer von einer Person oder aus Python-Code stammt. Menschliche Zeilennummern beginnen normalerweise bei 1, Listenindizes dagegen bei 0. Bei einer kleinen Datei lädt readlines() alle Zeilen und ermöglicht den direkten Zugriff über Indizes. Bei einer großen Datei kann enumerate() die Datei schrittweise durchlaufen. Für wiederholte Zugriffe bietet linecache den Zugriff über Zeilennummern und speichert Dateidaten im Cache; es ist daher keine Lösung mit konstantem Speicherbedarf.

Legen Sie zuerst eine Zeilennummerierung fest

Wenn jemand nach Zeile 3 fragt, lautet der entsprechende Listenindex 3 - 1, also 2. Auch enumerate() beginnt standardmäßig mit Index 0. Im Gegensatz dazu erwartet linecache.getline(path, 3) die menschliche Zeilennummer 3. Wenn Sie diese Konventionen ausdrücklich berücksichtigen, vermeiden Sie Verschiebungen um eine Zeile. Textzeilen enthalten häufig einen abschließenden Zeilenumbruch. Entfernen Sie ihn nur, wenn der Wert ohne diesen Leerraum angezeigt oder verglichen werden soll.

Lesen Sie ausgewählte Zeilen einer kleinen Datei mit readlines()

readlines() gibt eine Liste mit allen Zeilen zurück, einschließlich des Zeilenumbruchs, sofern einer vorhanden ist. Das ist praktisch, wenn die Datei problemlos in den Arbeitsspeicher passt und Sie möglicherweise auf mehrere Positionen zugreifen möchten. Das folgende eigenständige Beispiel erstellt eine temporäre Textdatei und gibt ihre dritte Zeile aus:

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "notes.txt"
    path.write_text("first\nsecond\nthird\nfourth\n", encoding="utf-8")
    with path.open(encoding="utf-8") as file:
        lines = file.readlines()
    print(lines[2].rstrip("\n"))

Für einen Bereich menschlicher Zeilennummern von first_line bis einschließlich last_line verwenden Sie den Slice lines[first_line - 1:last_line]. Das Slice-Ende ist exklusiv. Deshalb kann die menschliche Nummer der letzten Zeile selbst als Endindex verwendet werden. Wenn die angeforderte Zeile möglicherweise nicht existiert, prüfen Sie vor dem Zugriff, ob der Index kleiner als len(lines) ist.

Lesen Sie ausgewählte Zeilen einer großen Datei mit enumerate()

Wenn Sie die Datei direkt durchlaufen, müssen Sie keine Liste mit allen Zeilen erstellen. enumerate(file) liefert beim Lesen jeder Zeile einen bei null beginnenden Index; addieren Sie 1, wenn Sie eine menschliche Zeilennummer anzeigen möchten. Um eine spätere Zeile zu erreichen, müssen jedoch auch die vorherigen Zeilen durchlaufen werden. Dieses Verfahren eignet sich daher zum Reduzieren des Speicherbedarfs, nicht zum direkten Anspringen einer weit entfernten Zeile.

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "events.txt"
    path.write_text("start\nready\nconnected\nfinished\n", encoding="utf-8")
    wanted = {2, 4}
    with path.open(encoding="utf-8") as file:
        for line_number, line in enumerate(file, start=1):
            if line_number in wanted:
                print(line_number, line.rstrip("\n"))
            if line_number >= max(wanted):
                break

Mit start=1 wird die Schleifenvariable hier zu einer menschlichen Zeilennummer, wodurch Auswahlbedingungen leichter lesbar sein können. Enthält die Datei möglicherweise weniger Zeilen als angefordert, endet die Schleife einfach, ohne diese Anforderungen auszugeben.

Verwenden Sie linecache für wiederholte Zeilenzugriffe

Verwenden Sie linecache.getline(path, line_number), wenn Ihr Code wiederholt Zeilen anhand ihrer bei 1 beginnenden Nummer abfragt. Die Funktion gibt die Zeile als Text zurück, einschließlich eines vorhandenen Zeilenumbruchs. Eine fehlende Zeile wird durch eine leere Zeichenfolge dargestellt. linecache speichert Dateiinhalte für die Wiederverwendung im Cache. Das kann praktisch sein, wenn dieselbe Datei wiederholt abgefragt wird, doch die zwischengespeicherten Daten belegen weiterhin Speicher.

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

import linecache
from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "report.txt"
    path.write_text("header\nalpha\nbeta\n", encoding="utf-8")
    line = linecache.getline(str(path), 2)
    print(line.rstrip("\n"))
    linecache.clearcache()

Der ausdrückliche Aufruf von clearcache() gibt nach diesem Beispiel die zwischengespeicherten Einträge frei. Bei einer veränderlichen Datei ist es wichtig, dass der Cache aktuell ist: Wenn Ihr Programm die Datei geändert hat und die zwischengespeicherten Daten verwerfen soll, leeren Sie den Cache, bevor Sie erneut Zeilen abfragen.

Behandeln Sie Bereiche, fehlende Zeilen und Speichergrenzen

Wählen Sie readlines(), wenn der direkte Zugriff auf eine überschaubare Datei wichtiger ist, als ihren gesamten Inhalt im Speicher zu halten. Wählen Sie enumerate(), wenn Sie eine große Datei schrittweise verarbeiten oder nach einer bestimmten Zeile anhalten möchten; um eine spätere Zielzeile zu erreichen, müssen die vorherigen Zeilen dennoch gelesen werden. Wählen Sie linecache für wiederholte Abfragen nach Zeilennummer, sofern der Cache für Sie akzeptabel ist. Keine dieser Methoden kann eine Zeile hinter dem Dateiende abrufen: Der Zugriff auf einen Listenindex löst IndexError aus, beim Durchlaufen wird kein Treffer gefunden und getline() gibt eine leere Zeichenfolge zurück. Prüfen Sie die Anforderung oder behandeln Sie das Ergebnis passend zu den Anforderungen Ihres Programms.

Öffnen Sie Textdateien im Lesemodus, vorzugsweise mit einer with-Anweisung, damit die Datei am Ende des Blocks geschlossen wird. Geben Sie eine Codierung an, wenn die Codierung der Datei bekannt ist. Das Laden der gesamten Datei kann mit zunehmender Zeilenanzahl und Zeilenlänge viel Speicher beanspruchen; es gibt keinen allgemeinen Dateigrößen-Grenzwert, der für jeden Rechner und jede Arbeitslast passt. Beim schrittweisen Lesen bleiben weniger Zeilen in der Leseschleife gespeichert, aber ausgewählte Zeilen, die Sie sammeln, belegen weiterhin Speicher. Daher sind Zugriffsmuster und verfügbarer Speicher bessere Entscheidungshilfen als eine feste Größen- oder Geschwindigkeitsangabe.