Wie lese ich eine Datei Zeile für Zeile in eine Liste?

2027

Wie lese ich jede Zeile einer Datei in Python und speichere jede Zeile als Element in einer Liste?

Ich möchte die Datei Zeile für Zeile lesen und jede Zeile an das Ende der Liste anhängen.

Julie Raswick
quelle

Antworten:

2174
with open(filename) as f:
    content = f.readlines()
# you may also want to remove whitespace characters like `\n` at the end of each line
content = [x.strip() for x in content] 
SilentGhost
quelle
206
Nicht file.readlines()in einer forSchleife verwenden, ein Dateiobjekt selbst ist genug:lines = [line.rstrip('\n') for line in file]
jfs
88
Wenn Sie mit Big Data arbeiten, readlines()ist die Verwendung nicht sehr effizient, da dies zu MemoryError führen kann . In diesem Fall ist es besser, die Datei for line in f:mit jeder lineVariablen zu durchlaufen und mit ihr zu arbeiten .
DarkCygnus
7
Ich habe das Speicherprofil auf verschiedene Arten, die in den Antworten angegeben sind, mit dem hier erwähnten Verfahren überprüft . Die Speichernutzung ist weitaus besser, wenn jede Zeile aus der Datei gelesen und verarbeitet wird, wie von @DevShark hier vorgeschlagen . Das Halten aller Zeilen in einem Sammlungsobjekt ist keine gute Idee, wenn der Speicher eine Einschränkung darstellt oder die Datei groß ist. Die Ausführungszeit ist in beiden Ansätzen ähnlich.
Tirtha R
6
Funktioniert auch .rstrip()etwas schneller, wenn Sie Leerzeichen von den Zeilenenden entfernen.
Gringo Suave
Oneliner:with open(filename) as f: content = [i.strip() for i in f.readlines()]
Vishal Gupta vor
1002

Siehe Eingabe und Ausgabe :

with open('filename') as f:
    lines = f.readlines()

oder mit dem Strippen des Zeilenumbruchs:

with open('filename') as f:
    lines = [line.rstrip() for line in f]
Felix Kling
quelle
12
Besser, Verwendung f.read().splitlines(), die nicht entfernt Zeilenumbrüche
Mark
Ist die zweite Version mit for line in open(filename)Safe? Wird die Datei automatisch geschlossen?
Becko
2
Lesen Sie die Datei am besten zeilenweise, anstatt die gesamte Datei auf einmal in den Speicher einzulesen. Dies lässt sich mit großen Eingabedateien nicht gut skalieren. Siehe unten Antwort von Robert.
Brad Hein
1
lines = [x.rstrip('\n') for x in open('data\hsf.txt','r')]Wie kann ich die Datei nach dem Lesen schließen, wenn ich auf diese Weise schreibe?
Ramisa Anjum Aditi
2
Ja, bis zu dem Punkt, den andere hier ansprechen, obwohl es keine "Best Practice" ist, openohne den Kontextmanager (oder eine andere garantierte Methode zum Schließen) zu verwenden, ist dies nicht wirklich einer dieser Fälle - wenn das Objekt keine Referenzen mehr hat Dazu wird Müll gesammelt und die Datei geschlossen, was sofort bei Fehler oder nicht passieren sollte, wenn das Listenverständnis verarbeitet ist.
Aaron Hall
579

Dies ist expliziter als nötig, macht aber, was Sie wollen.

with open("file.txt") as file_in:
    lines = []
    for line in file_in:
        lines.append(line)
Robert
quelle
18
Ich bevorzuge diese Antwort, da nicht die gesamte Datei in den Speicher geladen werden muss (in diesem Fall wird sie zwar noch angehängt array, es können jedoch auch andere Umstände vorliegen ). Sicherlich kann dieser Ansatz bei großen Dateien Probleme mindern.
JohannesB
1
Das Anhängen an ein Array ist langsam. Ich kann mir keinen Anwendungsfall vorstellen, bei dem dies die beste Lösung ist.
Elias Strehle
@haccks ist es besser, weil es nicht die gesamte Datei in den Speicher lädt oder gibt es mehr?
OrigamiEye
4
Hinweis: Diese Lösung entfernt keine Zeilenumbrüche.
AMC
1
Diese Lösung lädt die gesamte Datei in den Speicher. Ich weiß nicht, warum die Leute denken, dass dies nicht der Fall ist.
andrebrait
274

Dies ergibt ein "Array" von Zeilen aus der Datei.

lines = tuple(open(filename, 'r'))

openGibt eine Datei zurück, die wiederholt werden kann. Wenn Sie eine Datei durchlaufen, erhalten Sie die Zeilen aus dieser Datei. tuplekann einen Iterator nehmen und eine Tupelinstanz für Sie aus dem Iterator instanziieren, den Sie ihm geben. linesist ein Tupel, das aus den Zeilen der Datei erstellt wird.

Noctis Skytower
quelle
31
@ MarshallFarrier Versuchen Sie es lines = open(filename).read().split('\n')stattdessen.
Noctis Skytower
16
schließt es die Datei?
Vanuan
5
@Vanuan Da es kein verbleibende Verweis auf die Datei nach der Zeile ausgeführt wird, der destructor sollte automatisch schließen Sie die Datei.
Noctis Skytower
30
@NoctisSkytower Ich finde lines = open(filename).read().splitlines()ein wenig sauberer, und ich glaube, dass es auch DOS-Zeilenenden besser handhabt.
Jaynp
8
@ mklement0 Unter der Annahme einer Datei mit 1000 Zeilen listnimmt a etwa 13,22% mehr Speicherplatz ein als a tuple. Ergebnisse kommen von from sys import getsizeof as g; i = [None] * 1000; round((g(list(i)) / g(tuple(i)) - 1) * 100, 2). Das Erstellen eines tupledauert etwa 4,17% länger als das Erstellen eines list(mit einer Standardabweichung von 0,16%). Die Ergebnisse stammen aus from timeit import timeit as t; round((t('tuple(i)', 'i = [None] * 1000') / t('list(i)', 'i = [None] * 1000') - 1) * 100, 2)30-maligem Laufen . Meine Lösung bevorzugt Platz gegenüber Geschwindigkeit, wenn die Notwendigkeit einer Veränderlichkeit unbekannt ist.
Noctis Skytower
194

Wenn Sie das \nenthalten möchten :

with open(fname) as f:
    content = f.readlines()

Wenn Sie nicht aufgenommen werden möchten \n:

with open(fname) as f:
    content = f.read().splitlines()
Eneko Alonso
quelle
168

Nach Pythons Methoden für Dateiobjekte ist die einfachste Möglichkeit, eine Textdatei in eine zu konvertieren, listfolgende:

with open('file.txt') as f:
    my_list = list(f)

Wenn Sie nur die Textdateizeilen durchlaufen müssen, können Sie Folgendes verwenden:

with open('file.txt') as f:
    for line in f:
       ...

Alte Antwort:

Verwenden von withund readlines():

with open('file.txt') as f:
    lines = f.readlines()

Wenn Sie die Datei nicht schließen möchten, funktioniert dieser Einzeiler:

lines = open('file.txt').readlines()

Der traditionelle Weg:

f = open('file.txt') # Open file on read mode
lines = f.read().split("\n") # Create a list containing all lines
f.close() # Close file
CONvid19
quelle
150

Sie können einfach Folgendes tun, wie vorgeschlagen wurde:

with open('/your/path/file') as f:
    my_lines = f.readlines()

Beachten Sie, dass dieser Ansatz zwei Nachteile hat:

1) Sie speichern alle Zeilen im Speicher. Im Allgemeinen ist dies eine sehr schlechte Idee. Die Datei kann sehr groß sein und Ihnen kann der Speicher ausgehen. Auch wenn es nicht groß ist, ist es einfach eine Verschwendung von Speicher.

2) Dies erlaubt nicht die Verarbeitung jeder Zeile, während Sie sie lesen. Wenn Sie Ihre Zeilen danach verarbeiten, ist dies nicht effizient (erfordert zwei Durchgänge anstelle von einem).

Ein besserer Ansatz für den allgemeinen Fall wäre der folgende:

with open('/your/path/file') as f:
    for line in f:
        process(line)

Wo Sie Ihre Prozessfunktion nach Ihren Wünschen definieren. Zum Beispiel:

def process(line):
    if 'save the world' in line.lower():
         superman.save_the_world()

(Die Implementierung der SupermanKlasse bleibt Ihnen als Übung überlassen).

Dies funktioniert gut für jede Dateigröße und Sie gehen Ihre Datei in nur 1 Durchgang durch. So funktionieren generische Parser normalerweise.

DevShark
quelle
5
Dies war genau das, was ich brauchte - und danke, dass Sie die Nachteile erklärt haben. Als Anfänger in Python ist es großartig zu verstehen, warum eine Lösung die Lösung ist. Prost!
Ephexx
5
Denk ein bisschen mehr nach Corey. Möchten Sie wirklich, dass Ihr Computer jede Zeile liest, ohne jemals etwas mit diesen Zeilen zu tun? Sicherlich können Sie erkennen, dass Sie sie immer auf die eine oder andere Weise verarbeiten müssen.
DevShark
5
Sie müssen immer etwas mit den Linien tun. Es kann so einfach sein, wie die Zeilen zu drucken oder zu zählen. Es hat keinen Wert, wenn Ihr Prozess die Zeilen im Speicher liest, aber nichts damit macht.
DevShark
2
Sie müssen immer etwas mit ihnen machen. Ich denke, der Punkt, den Sie ansprechen möchten, ist, dass Sie möglicherweise eine Funktion auf alle gleichzeitig anwenden möchten, anstatt nacheinander. Das ist in der Tat manchmal der Fall. Aus Speichersicht ist dies jedoch sehr ineffizient und verhindert, dass Sie Dateien lesen können, wenn der Footprint größer als Ihr Ram ist. Aus diesem Grund funktionieren generische Parser normalerweise so, wie ich es beschrieben habe.
DevShark
2
@PierreOcinom das ist richtig. Da die Datei im schreibgeschützten Modus geöffnet ist, können Sie die Originaldatei nicht mit dem obigen Code ändern. Verwenden Sieopen('file_path', 'r+')
DevShark
64

Daten in Liste

Angenommen, wir haben eine Textdatei mit unseren Daten wie in den folgenden Zeilen:

Inhalt der Textdatei:

line 1
line 2
line 3
  • Öffnen Sie das cmd im selben Verzeichnis (klicken Sie mit der rechten Maustaste und wählen Sie cmd oder PowerShell).
  • Führen Sie aus pythonund schreiben Sie im Interpreter:

Das Python-Skript:

>>> with open("myfile.txt", encoding="utf-8") as file:
...     x = [l.strip() for l in file]
>>> x
['line 1','line 2','line 3']

Verwenden von Anhängen:

x = []
with open("myfile.txt") as file:
    for l in file:
        x.append(l.strip())

Oder:

>>> x = open("myfile.txt").read().splitlines()
>>> x
['line 1', 'line 2', 'line 3']

Oder:

>>> x = open("myfile.txt").readlines()
>>> x
['linea 1\n', 'line 2\n', 'line 3\n']

Oder:

def print_output(lines_in_textfile):
    print("lines_in_textfile =", lines_in_textfile)

y = [x.rstrip() for x in open("001.txt")]
print_output(y)

with open('001.txt', 'r', encoding='utf-8') as file:
    file = file.read().splitlines()
    print_output(file)

with open('001.txt', 'r', encoding='utf-8') as file:
    file = [x.strip() for x in file.readlines()]
    print_output(file)

Ausgabe:

lines_in_textfile = ['line 1', 'line 2', 'line 3']
lines_in_textfile = ['line 1', 'line 2', 'line 3']
lines_in_textfile = ['line 1', 'line 2', 'line 3']
Giovanni G. PY
quelle
ist das encoding="utf-8"erforderlich?
Mausy5043
@ Mausy5043 nein, aber wenn Sie eine Textdatei lesen, können Sie einen seltsamen Charakter haben (besonders auf Italienisch)
Giovanni G. PY
1
read().splitlines()wird Ihnen von Python zur Verfügung gestellt: Es ist einfach readlines()(was wahrscheinlich schneller ist, da es weniger verschwenderisch ist).
Eric O Lebigot
1
@EricOLebigot aus den gezeigten Beispielen sieht es so aus read().splitlines()und erzeugt readlines()nicht die gleiche Ausgabe. Sind Sie sicher, dass sie gleichwertig sind?
Craq
1
Wenn Sie nur Readlines verwenden, müssen Sie die Strip-Methode verwenden, um das \ n im Text zu entfernen. Daher habe ich die letzten Beispiele mithilfe eines Listenverständnisses geändert, um in beiden Fällen dieselbe Ausgabe zu erzielen. Wenn Sie also read (). Readlines () verwenden, haben Sie ein "sauberes" Element mit der Zeile und ohne das Zeilenumbruchzeichen. Andernfalls müssen Sie das tun, was Sie im obigen Code sehen.
Giovanni G. PY
43

Um eine Datei in eine Liste einzulesen, müssen Sie drei Dinge tun:

  • Öffne die Datei
  • Lesen Sie die Datei
  • Speichern Sie den Inhalt als Liste

Glücklicherweise macht es Python sehr einfach, diese Dinge zu tun. Der kürzeste Weg, eine Datei in eine Liste einzulesen, ist:

lst = list(open(filename))

Ich werde jedoch noch einige Erklärungen hinzufügen.

Datei öffnen

Ich gehe davon aus, dass Sie eine bestimmte Datei öffnen möchten und sich nicht direkt mit einem Datei-Handle (oder einem dateiähnlichen Handle) befassen. Die am häufigsten verwendete Funktion zum Öffnen einer Datei in Python ist open, dass in Python 2.7 ein obligatorisches und zwei optionale Argumente erforderlich sind:

  • Dateiname
  • Modus
  • Pufferung (Ich werde dieses Argument in dieser Antwort ignorieren)

Der Dateiname sollte eine Zeichenfolge sein, die den Pfad zur Datei darstellt . Zum Beispiel:

open('afile')   # opens the file named afile in the current working directory
open('adir/afile')            # relative path (relative to the current working directory)
open('C:/users/aname/afile')  # absolute path (windows)
open('/usr/local/afile')      # absolute path (linux)

Beachten Sie, dass die Dateierweiterung angegeben werden muss. Dies ist besonders wichtig für Windows-Benutzer, da Dateierweiterungen wie .txtoder .docusw. standardmäßig ausgeblendet sind wenn sie im Explorer angezeigt werden.

Das zweite Argument ist das mode, es istr standardmäßig "schreibgeschützt". Genau das brauchen Sie in Ihrem Fall.

Wenn Sie jedoch tatsächlich eine Datei erstellen und / oder in eine Datei schreiben möchten, benötigen Sie hier ein anderes Argument. Es gibt eine ausgezeichnete Antwort, wenn Sie einen Überblick wünschen .

Zum Lesen einer Datei können Sie diese weglassen modeoder explizit übergeben:

open(filename)
open(filename, 'r')

Beide öffnen die Datei im schreibgeschützten Modus. Wenn Sie eine Binärdatei unter Windows einlesen möchten, müssen Sie den folgenden Modus verwenden rb:

open(filename, 'rb')

Auf anderen Plattformen wird der 'b'(Binärmodus) einfach ignoriert.


Nachdem ich nun gezeigt habe, wie opendie Datei erstellt wird, lassen Sie uns darüber sprechen, dass Sie sie immer wieder benötigen close. Andernfalls bleibt ein offenes Datei-Handle für die Datei erhalten, bis der Prozess beendet wird (oder Python das Datei-Handle beschädigt).

Während Sie verwenden könnten:

f = open(filename)
# ... do stuff with f
f.close()

Dadurch kann die Datei nicht geschlossen werden, wenn etwas dazwischen liegt openund closeeine Ausnahme ausgelöst wird. Sie können dies vermeiden, indem Sie ein tryund verwenden finally:

f = open(filename)
# nothing in between!
try:
    # do stuff with f
finally:
    f.close()

Python bietet jedoch Kontextmanager mit einer schöneren Syntax (die jedoch openfast identisch mit der tryund der finallyoben genannten ist):

with open(filename) as f:
    # do stuff with f
# The file is always closed after the with-scope ends.

Der letzte Ansatz ist der empfohlene Ansatz zum Öffnen einer Datei in Python!

Datei lesen

Okay, Sie haben die Datei geöffnet. Wie kann man sie jetzt lesen?

Die openFunktion gibt ein fileObjekt zurück und unterstützt das Pythons-Iterationsprotokoll. Jede Iteration gibt Ihnen eine Zeile:

with open(filename) as f:
    for line in f:
        print(line)

Dadurch wird jede Zeile der Datei gedruckt. Beachten Sie jedoch, dass jede Zeile \nam Ende ein Zeilenumbruchzeichen enthält (Sie möchten möglicherweise überprüfen, ob Ihr Python mit universeller Zeilenumbruchunterstützung erstellt wurde - andernfalls können Sie auch \r\nWindows oder \rMac als Zeilenumbrüche verwenden). Wenn Sie dies nicht möchten, können Sie einfach das letzte Zeichen (oder die letzten beiden Zeichen unter Windows) entfernen:

with open(filename) as f:
    for line in f:
        print(line[:-1])

Aber die letzte Zeile hat nicht unbedingt eine nachfolgende neue Zeile, daher sollte man diese nicht verwenden. Man könnte prüfen, ob es mit einem nachgestellten Zeilenumbruch endet, und wenn ja, entfernen Sie es:

with open(filename) as f:
    for line in f:
        if line.endswith('\n'):
            line = line[:-1]
        print(line)

Sie können jedoch einfach alle Leerzeichen (einschließlich des \nZeichens) am Ende der Zeichenfolge entfernen. Dadurch werden auch alle anderen nachgestellten Leerzeichen entfernt, sodass Sie vorsichtig sein müssen, wenn diese wichtig sind:

with open(filename) as f:
    for line in f:
        print(f.rstrip())

Wenn die Zeilen jedoch mit \r\n(Windows "newlines") enden .rstrip(), kümmert sich das auch um das \r!

Speichern Sie den Inhalt als Liste

Nachdem Sie nun wissen, wie Sie die Datei öffnen und lesen, ist es Zeit, den Inhalt in einer Liste zu speichern. Die einfachste Möglichkeit wäre, die listFunktion zu verwenden:

with open(filename) as f:
    lst = list(f)

Wenn Sie die nachfolgenden Zeilenumbrüche entfernen möchten, können Sie stattdessen ein Listenverständnis verwenden:

with open(filename) as f:
    lst = [line.rstrip() for line in f]

Oder noch einfacher: Die .readlines()Methode des fileObjekts gibt standardmäßig eine listder Zeilen zurück:

with open(filename) as f:
    lst = f.readlines()

Dies schließt auch die nachfolgenden Zeilenumbruchzeichen ein. Wenn Sie sie nicht möchten, würde ich den [line.rstrip() for line in f]Ansatz empfehlen, da dadurch vermieden wird, dass zwei Listen mit allen Zeilen im Speicher bleiben .

Es gibt eine zusätzliche Option, um die gewünschte Ausgabe zu erhalten, diese ist jedoch eher "suboptimal": readdie vollständige Datei in einer Zeichenfolge und dann in Zeilenumbrüche aufgeteilt:

with open(filename) as f:
    lst = f.read().split('\n')

oder:

with open(filename) as f:
    lst = f.read().splitlines()

Diese kümmern sich automatisch um die nachfolgenden Zeilenumbrüche, da das splitZeichen nicht enthalten ist. Sie sind jedoch nicht ideal, da Sie die Datei als Zeichenfolge und als Liste der Zeilen im Speicher behalten!

Zusammenfassung

  • Verwenden with open(...) as fSie diese Option beim Öffnen von Dateien, da Sie sich nicht darum kümmern müssen, die Datei selbst zu schließen, und sie auch dann geschlossen wird, wenn eine Ausnahme auftritt.
  • fileObjekte unterstützen das Iterationsprotokoll, sodass das zeilenweise Lesen einer Datei so einfach ist wie for line in the_file_object:.
  • Durchsuchen Sie immer die Dokumentation nach den verfügbaren Funktionen / Klassen. Meistens passt es perfekt zu der Aufgabe oder mindestens ein oder zwei gute. Die offensichtliche Wahl in diesem Fall wäre, readlines()aber wenn Sie die Zeilen verarbeiten möchten, bevor Sie sie in der Liste speichern, würde ich ein einfaches Listenverständnis empfehlen.
MSeifert
quelle
Der letzte Ansatz ist der empfohlene Ansatz zum Öffnen einer Datei in Python! Warum ist es dann zuletzt? Wird die überwiegende Mehrheit der Menschen nicht nur einen Blick auf die ersten Zeilen einer Antwort werfen, bevor sie fortfahren?
AMC
@AMC Ich habe nicht viel darüber nachgedacht, als ich die Antwort schrieb. Denkst du, ich sollte es ganz oben auf die Antwort setzen?
MSeifert
Es könnte am besten sein, ja. Mir ist auch gerade aufgefallen, dass Sie Python 2 erwähnen, damit auch dieses aktualisiert werden kann.
AMC
Ah, die Frage wurde ursprünglich mit python-2.x getaggt. Es kann sinnvoll sein, es allgemeiner zu aktualisieren. Ich werde sehen, ob ich das nächste Mal dazu komme. Vielen Dank für Ihre Vorschläge. Sehr geschätzt!
MSeifert
42

Saubere und pythonische Art, die Zeilen einer Datei in eine Liste einzulesen


In erster Linie sollten Sie sich darauf konzentrieren, Ihre Datei zu öffnen und ihren Inhalt effizient und pythonisch zu lesen. Hier ist ein Beispiel dafür, wie ich persönlich NICHT bevorzuge:

infile = open('my_file.txt', 'r')  # Open the file for reading.

data = infile.read()  # Read the contents of the file.

infile.close()  # Close the file since we're done using it.

Stattdessen bevorzuge ich die folgende Methode zum Öffnen von Dateien zum Lesen und Schreiben, da sie sehr sauber ist und keinen zusätzlichen Schritt zum Schließen der Datei erfordert, sobald Sie sie verwendet haben. In der folgenden Anweisung öffnen wir die Datei zum Lesen und weisen sie der Variablen 'infile' zu. Sobald der Code in dieser Anweisung ausgeführt wurde, wird die Datei automatisch geschlossen.

# Open the file for reading.
with open('my_file.txt', 'r') as infile:

    data = infile.read()  # Read the contents of the file into memory.

Jetzt müssen wir uns darauf konzentrieren, diese Daten in eine zu bringen Python-Liste aufzunehmen, da sie iterierbar, effizient und flexibel sind. In Ihrem Fall besteht das gewünschte Ziel darin, jede Zeile der Textdatei in ein separates Element zu bringen. Um dies zu erreichen, verwenden wir die splitlines () -Methode wie folgt:

# Return a list of the lines, breaking at line boundaries.
my_list = data.splitlines()

Das Endprodukt:

# Open the file for reading.
with open('my_file.txt', 'r') as infile:

    data = infile.read()  # Read the contents of the file into memory.

# Return a list of the lines, breaking at line boundaries.
my_list = data.splitlines()

Testen unseres Codes:

  • Inhalt der Textdatei:
     A fost odatã ca-n povesti,
     A fost ca niciodatã,
     Din rude mãri împãrãtesti,
     O prea frumoasã fatã.
  • Druckanweisungen zu Testzwecken:
    print my_list  # Print the list.

    # Print each line in the list.
    for line in my_list:
        print line

    # Print the fourth element in this list.
    print my_list[3]
  • Ausgabe (aufgrund von Unicode-Zeichen unterschiedlich aussehend):
     ['A fost odat\xc3\xa3 ca-n povesti,', 'A fost ca niciodat\xc3\xa3,',
     'Din rude m\xc3\xa3ri \xc3\xaemp\xc3\xa3r\xc3\xa3testi,', 'O prea
     frumoas\xc3\xa3 fat\xc3\xa3.']

     A fost odatã ca-n povesti, A fost ca niciodatã, Din rude mãri
     împãrãtesti, O prea frumoasã fatã.

     O prea frumoasã fatã.
Johnny
quelle
30

Die in Python 3.4 eingeführte pathlibMethode bietet eine sehr praktische Methode zum Einlesen von Text aus Dateien:

from pathlib import Path
p = Path('my_text_file')
lines = p.read_text().splitlines()

(Der splitlinesAufruf verwandelt ihn von einer Zeichenfolge, die den gesamten Inhalt der Datei enthält, in eine Liste von Zeilen in der Datei.)

pathlibhat viele praktische Annehmlichkeiten. read_textist nett und prägnant, und Sie müssen sich keine Gedanken über das Öffnen und Schließen der Datei machen. Wenn Sie mit der Datei nur alles auf einmal lesen müssen, ist dies eine gute Wahl.

LangeHaare
quelle
29

Hier ist eine weitere Option, bei der Listenverständnisse für Dateien verwendet werden.

lines = [line.rstrip() for line in open('file.txt')]

Dies sollte effizienter sein, da der größte Teil der Arbeit im Python-Interpreter erledigt wird.

user1833244
quelle
10
rstrip()entfernt möglicherweise alle nachgestellten Leerzeichen, nicht nur die \n; verwenden .rstrip('\n').
mklement0
Dies garantiert auch nicht, dass die Datei nach dem Lesen aller Python-Implementierungen geschlossen wird (obwohl dies in CPython, der Haupt-Python-Implementierung, der Fall ist).
Mark Amery
1
Dies sollte effizienter sein, da der größte Teil der Arbeit im Python-Interpreter erledigt wird. Was bedeutet das?
AMC
28
f = open("your_file.txt",'r')
out = f.readlines() # will append in the list out

Jetzt ist Variable out eine Liste (Array) von dem, was Sie wollen. Sie könnten entweder tun:

for line in out:
    print (line)

Oder:

for line in f:
    print (line)

Sie erhalten die gleichen Ergebnisse.

Schimmel
quelle
27

Lesen und Schreiben von Textdateien mit Python 2 und Python 3; es funktioniert mit Unicode

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Define data
lines = ['     A first string  ',
         'A Unicode sample: €',
         'German: äöüß']

# Write text file
with open('file.txt', 'w') as fp:
    fp.write('\n'.join(lines))

# Read text file
with open('file.txt', 'r') as fp:
    read_lines = fp.readlines()
    read_lines = [line.rstrip('\n') for line in read_lines]

print(lines == read_lines)

Dinge zu beachten:

  • withist ein sogenannter Kontextmanager . Es stellt sicher, dass die geöffnete Datei wieder geschlossen wird.
  • Alle Lösungen hier, die einfach machen .strip()oder .rstrip()nicht reproduzieren können, linesda sie auch den Leerraum entfernen.

Allgemeine Dateienden

.txt

Erweitertes Schreiben / Lesen von Dateien

Für Ihre Anwendung kann Folgendes wichtig sein:

  • Unterstützung durch andere Programmiersprachen
  • Lese- / Schreibleistung
  • Kompaktheit (Dateigröße)

Siehe auch: Vergleich der Datenserialisierungsformate

Wenn Sie eher nach einer Möglichkeit suchen, Konfigurationsdateien zu erstellen, lesen Sie möglicherweise meinen kurzen Artikel Konfigurationsdateien in Python .

Martin Thoma
quelle
26

Eine andere Option ist numpy.genfromtxtzum Beispiel:

import numpy as np
data = np.genfromtxt("yourfile.dat",delimiter="\n")

Dadurch wird dataein NumPy-Array mit so vielen Zeilen erstellt, wie in Ihrer Datei enthalten sind.

atomh33ls
quelle
25

Wenn Sie eine Datei über die Befehlszeile oder über stdin lesen möchten, können Sie auch das folgende fileinputModul verwenden:

# reader.py
import fileinput

content = []
for line in fileinput.input():
    content.append(line.strip())

fileinput.close()

Übergeben Sie Dateien wie folgt:

$ python reader.py textfile.txt 

Lesen Sie hier mehr: http://docs.python.org/2/library/fileinput.html

oliland
quelle
20

Der einfachste Weg, es zu tun

Ein einfacher Weg ist:

  1. Lesen Sie die gesamte Datei als Zeichenfolge
  2. Teilen Sie die Zeichenfolge Zeile für Zeile

In einer Zeile würde das geben:

lines = open('C:/path/file.txt').read().splitlines()

Dies ist jedoch ziemlich ineffizient, da dadurch 2 Versionen des Inhalts im Speicher gespeichert werden (wahrscheinlich kein großes Problem für kleine Dateien, aber immer noch). [Danke Mark Amery].

Es gibt zwei einfachere Möglichkeiten:

  1. Verwenden der Datei als Iterator
lines = list(open('C:/path/file.txt'))
# ... or if you want to have a list without EOL characters
lines = [l.rstrip() for l in open('C:/path/file.txt')]
  1. Wenn Sie Python 3.4 oder höher verwenden pathlib, erstellen Sie besser einen Pfad für Ihre Datei, den Sie für andere Vorgänge in Ihrem Programm verwenden können:
from pathlib import Path
file_path = Path("C:/path/file.txt") 
lines = file_path.read_text().split_lines()
# ... or ... 
lines = [l.rstrip() for l in file_path.open()]
Jean-Francois T.
quelle
Dies ist ein schlechter Ansatz. Zum einen ist das Anrufen .read().splitlines()in keiner Weise "einfacher" als nur das Anrufen .readlines(). Zum anderen ist es speichereffizient; Sie speichern unnötigerweise zwei Versionen des Dateiinhalts (die von zurückgegebene einzelne Zeichenfolge .read()und die Liste der von zurückgegebenen Zeichenfolgen splitlines()) gleichzeitig im Speicher.
Mark Amery
@ MarkAmery True. Vielen Dank, dass Sie dies hervorgehoben haben. Ich habe meine Antwort aktualisiert.
Jean-Francois T.
14

Verwenden Sie einfach die Funktionen splitlines (). Hier ist ein Beispiel.

inp = "file.txt"
data = open(inp)
dat = data.read()
lst = dat.splitlines()
print lst
# print(lst) # for python 3

In der Ausgabe haben Sie die Liste der Zeilen.

Abdullah Bilal
quelle
Speicher ineffizient im Vergleich zur Verwendung .readlines(). Dadurch werden zwei Kopien des Dateiinhalts gleichzeitig gespeichert (eine als einzelne große Zeichenfolge, eine als Liste von Zeilen).
Mark Amery
11

Wenn Sie mit einer sehr großen / riesigen Datei konfrontiert werden und schneller lesen möchten (stellen Sie sich vor, Sie befinden sich in einem Topcoder / Hackerrank-Codierungswettbewerb), lesen Sie möglicherweise einen erheblich größeren Zeilenabschnitt gleichzeitig in einen Speicherpuffer Iterieren Sie einfach Zeile für Zeile auf Dateiebene.

buffersize = 2**16
with open(path) as f: 
    while True:
        lines_buffer = f.readlines(buffersize)
        if not lines_buffer:
            break
        for line in lines_buffer:
            process(line)
pambda
quelle
Was macht process (line)? Ich erhalte die Fehlermeldung, dass keine solche Variable definiert ist. Ich denke, etwas muss importiert werden und ich habe versucht, Multiprocessing zu importieren. Process, aber das ist es nicht, denke ich. Könnten Sie bitte näher darauf eingehen? Danke
Newskooler
1
process(line)ist eine Funktion, die Sie implementieren müssen, um die Daten zu verarbeiten. Anstelle dieser Zeile print(line)wird beispielsweise jede Zeile aus dem Zeilenpuffer gedruckt , wenn Sie sie verwenden .
Khanal
f.readlines (Puffergröße) gibt einen unveränderlichen Puffer zurück. Wenn Sie direkt in Ihren Puffer einlesen möchten, müssen Sie die Funktion readinto () verwenden. Ich werde viel schneller sein.
David Dehghan
7

Die einfachsten Möglichkeiten, dies mit einigen zusätzlichen Vorteilen zu tun, sind:

lines = list(open('filename'))

oder

lines = tuple(open('filename'))

oder

lines = set(open('filename'))

In diesem Fall setmüssen wir uns daran erinnern, dass wir die Zeilenreihenfolge nicht beibehalten und die duplizierten Zeilen entfernen.

Unten habe ich eine wichtige Ergänzung von @MarkAmery hinzugefügt :

Da Sie weder das Dateiobjekt aufrufen .closenoch eine withAnweisung verwenden, wird die Datei in einigen Python- Implementierungen nach dem Lesen möglicherweise nicht geschlossen, und Ihr Prozess verliert ein offenes Dateihandle .

In CPython (der normalen Python- Implementierung, die die meisten Benutzer verwenden) ist dies kein Problem, da das Dateiobjekt sofort durch Müll gesammelt wird und die Datei geschlossen wird. Es wird jedoch allgemein als bewährte Methode angesehen, Folgendes zu tun :

with open('filename') as f: lines = list(f) 

um sicherzustellen, dass die Datei geschlossen wird, unabhängig davon, welche Python- Implementierung Sie verwenden.

simhumileco
quelle
1
Da Sie weder das Dateiobjekt aufrufen .closenoch eine withAnweisung verwenden, wird die Datei in einigen Python-Implementierungen nach dem Lesen möglicherweise nicht geschlossen, und Ihr Prozess verliert ein offenes Dateihandle. In CPython (der normalen Python-Implementierung, die die meisten Benutzer verwenden) ist dies kein Problem, da das Dateiobjekt sofort durch Müll gesammelt wird und die Datei geschlossen wird. Es wird jedoch allgemein als bewährte Methode angesehen, dies with open('filename') as f: lines = list(f)sicherzustellen Die Datei wird geschlossen, unabhängig davon, welche Python-Implementierung Sie verwenden.
Mark Amery
Vielen Dank für Ihren tollen Kommentar @MarkAmery! Ich weiß das wirklich zu schätzen.
Simhumileco
1
@simhumileco Warum hat die beste (richtige) Lösung zuletzt?
AMC
@AMC, weil ich zuerst die einfachsten Wege und für die Konsistenz der Argumentation zeigen wollte.
simhumileco
Außerdem hoffe ich, dass meine Antwort so gemacht wird, dass sie kurz und leicht zu lesen ist.
simhumileco
4

Benutze das:

import pandas as pd
data = pd.read_csv(filename) # You can also add parameters such as header, sep, etc.
array = data.values

dataist ein Datenrahmentyp und verwendet Werte, um ndarray abzurufen. Sie können eine Liste auch mit abrufen array.tolist().

Null
quelle
pandas.read_csv()ist zum Lesen von CSV- Daten, wie ist es hier angebracht?
AMC
4

Gliederung und Zusammenfassung

filenameFühren Sie mit a , indem Sie die Datei von einem Path(filename)Objekt aus oder direkt mit open(filename) as fbearbeiten, einen der folgenden Schritte aus:

  • list(fileinput.input(filename))
  • mit with path.open() as fanrufenf.readlines()
  • list(f)
  • path.read_text().splitlines()
  • path.read_text().splitlines(keepends=True)
  • iterieren Sie über fileinput.inputoder fund list.appendjede Zeile einzeln
  • passieren fzu einem gebundenen list.extendVerfahren
  • Verwendung fin einem Listenverständnis

Ich erkläre den Anwendungsfall für jeden unten.

Wie lese ich in Python eine Datei Zeile für Zeile?

Dies ist eine ausgezeichnete Frage. Lassen Sie uns zunächst einige Beispieldaten erstellen:

from pathlib import Path
Path('filename').write_text('foo\nbar\nbaz')

Dateiobjekte sind faule Iteratoren, also iterieren Sie einfach darüber.

filename = 'filename'
with open(filename) as f:
    for line in f:
        line # do something with the line

Wenn Sie mehrere Dateien haben, verwenden Sie alternativ einen fileinput.inputanderen faulen Iterator. Mit nur einer Datei:

import fileinput

for line in fileinput.input(filename): 
    line # process the line

oder übergeben Sie für mehrere Dateien eine Liste mit Dateinamen:

for line in fileinput.input([filename]*2): 
    line # process the line

Wieder fund fileinput.inputdarüber sind / return faule Iteratoren. Sie können einen Iterator nur einmal verwenden. Um Funktionscode bereitzustellen und gleichzeitig die Ausführlichkeit zu vermeiden, verwende ich den etwas knapperen fileinput.input(filename)Punkt, der von hier aus vorgeschlagen wird.

Wie lese ich in Python eine Datei Zeile für Zeile in eine Liste?

Ah, aber du willst es aus irgendeinem Grund in einer Liste? Ich würde das nach Möglichkeit vermeiden. Aber wenn Sie darauf bestehen ... geben Sie das Ergebnis einfach fileinput.input(filename)an list:

list(fileinput.input(filename))

Eine andere direkte Antwort ist ein Aufruf f.readlines, der den Inhalt der Datei zurückgibt (bis zu einer optionalen hintAnzahl von Zeichen, so dass Sie könnten diese in mehrere Listen auf diese Weise brechen).

Sie können auf zwei Arten zu diesem Dateiobjekt gelangen. Eine Möglichkeit besteht darin, den Dateinamen an das openeingebaute zu übergeben:

filename = 'filename'

with open(filename) as f:
    f.readlines()

oder mit dem neuen Path-Objekt aus dem pathlibModul (das ich sehr gern habe und von nun an verwenden werde):

from pathlib import Path

path = Path(filename)

with path.open() as f:
    f.readlines()

list verbraucht auch den Datei-Iterator und gibt eine Liste zurück - eine ziemlich direkte Methode:

with path.open() as f:
    list(f)

Wenn es Ihnen nichts ausmacht, den gesamten Text vor dem Teilen als einzelne Zeichenfolge in den Speicher einzulesen, können Sie dies als Einzeiler mit dem PathObjekt und der splitlines()Zeichenfolgenmethode tun . splitlinesEntfernt standardmäßig die Zeilenumbrüche:

path.read_text().splitlines()

Wenn Sie die Zeilenumbrüche behalten möchten, übergeben Sie keepends=True:

path.read_text().splitlines(keepends=True)

Ich möchte die Datei Zeile für Zeile lesen und jede Zeile an das Ende der Liste anhängen.

Das ist etwas albern, da wir das Endergebnis mit verschiedenen Methoden leicht demonstriert haben. Möglicherweise müssen Sie jedoch die Zeilen filtern oder bearbeiten, während Sie Ihre Liste erstellen. Lassen Sie uns diese Anfrage also humorisieren.

Mit list.appendkönnen Sie jede Zeile filtern oder bearbeiten, bevor Sie sie anhängen:

line_list = []
for line in fileinput.input(filename):
    line_list.append(line)

line_list

Die Verwendung list.extendwäre etwas direkter und möglicherweise nützlich, wenn Sie eine bereits vorhandene Liste haben:

line_list = []
line_list.extend(fileinput.input(filename))
line_list

Oder idiomatischer, wir könnten stattdessen ein Listenverständnis verwenden und es gegebenenfalls abbilden und filtern:

[line for line in fileinput.input(filename)]

Oder noch direkter, um den Kreis zu schließen, übergeben Sie ihn einfach an die Liste, um eine neue Liste direkt zu erstellen, ohne die Linien zu bearbeiten:

list(fileinput.input(filename))

Fazit

Sie haben viele Möglichkeiten gesehen, Zeilen aus einer Datei in eine Liste zu übertragen, aber ich würde empfehlen, dass Sie vermeiden, große Datenmengen in einer Liste zu materialisieren, und stattdessen Pythons verzögerte Iteration verwenden, um die Daten nach Möglichkeit zu verarbeiten.

Das heißt, bevorzugen fileinput.inputoder with path.open() as f.

Aaron Hall
quelle
4

Falls das Dokument auch leere Zeilen enthält, lese ich den Inhalt gerne ein und leite ihn durch filter, um leere Zeichenfolgenelemente zu vermeiden

with open(myFile, "r") as f:
    excludeFileContent = list(filter(None, f.read().splitlines()))
jeanggi90
quelle
1
Das ist unpythonisch, sei vorsichtig.
AMC
3

Sie können auch den Befehl loadtxt in NumPy verwenden. Dies sucht nach weniger Bedingungen als genfromtxt, sodass es möglicherweise schneller ist.

import numpy
data = numpy.loadtxt(filename, delimiter="\n")
asampat3090
quelle
2

Ich benutze gerne folgendes. Lesen Sie die Zeilen sofort.

contents = []
for line in open(filepath, 'r').readlines():
    contents.append(line.strip())

Oder mit Listenverständnis:

contents = [line.strip() for line in open(filepath, 'r').readlines()]
Daniel
quelle
2
Es besteht keine Notwendigkeit für readlines(), was sogar eine Speicherstrafe verursacht. Sie können es einfach entfernen, da das Durchlaufen einer (Text-) Datei jede Zeile der Reihe nach ergibt.
Eric O Lebigot
2
Sie sollten eine withAnweisung verwenden, um die Datei zu öffnen (und implizit zu schließen).
Aran-Fey
2

Ich würde eine der unten genannten Methoden ausprobieren. Die von mir verwendete Beispieldatei hat den Namen dummy.txt. Die Datei finden Sie hier . Ich gehe davon aus, dass sich die Datei im selben Verzeichnis wie der Code befindet (Sie können sie ändern fpath, um den richtigen Dateinamen und Ordnerpfad einzuschließen.)

In beiden unten genannten Beispielen wird die gewünschte Liste von angegeben lst.

1.> Erste Methode :

fpath = 'dummy.txt'
with open(fpath, "r") as f: lst = [line.rstrip('\n \t') for line in f]

print lst
>>>['THIS IS LINE1.', 'THIS IS LINE2.', 'THIS IS LINE3.', 'THIS IS LINE4.']

2.> Bei der zweiten Methode kann das Modul csv.reader aus der Python Standard Library verwendet werden :

import csv
fpath = 'dummy.txt'
with open(fpath) as csv_file:
    csv_reader = csv.reader(csv_file, delimiter='   ')
    lst = [row[0] for row in csv_reader] 

print lst
>>>['THIS IS LINE1.', 'THIS IS LINE2.', 'THIS IS LINE3.', 'THIS IS LINE4.']

Sie können eine der beiden Methoden verwenden. Die für die Erstellung benötigte Zeit lstist bei beiden Methoden nahezu gleich.

Siddharth Satpathy
quelle
1
Was ist der Vorteil des zweiten Ansatzes? Warum eine zusätzliche Bibliothek aufrufen, die in Randfällen (Trennzeichen und Anführungszeichen) hinzugefügt wird?
Charlie Harding
Wofür ist das delimiter=' 'Argument?
AMC
2

Hier ist eine Python (3) Helfer Bibliothek - Klasse, die ich Datei zu vereinfachen , verwenden I / O:

import os

# handle files using a callback method, prevents repetition
def _FileIO__file_handler(file_path, mode, callback = lambda f: None):
  f = open(file_path, mode)
  try:
    return callback(f)
  except Exception as e:
    raise IOError("Failed to %s file" % ["write to", "read from"][mode.lower() in "r rb r+".split(" ")])
  finally:
    f.close()


class FileIO:
  # return the contents of a file
  def read(file_path, mode = "r"):
    return __file_handler(file_path, mode, lambda rf: rf.read())

  # get the lines of a file
  def lines(file_path, mode = "r", filter_fn = lambda line: len(line) > 0):
    return [line for line in FileIO.read(file_path, mode).strip().split("\n") if filter_fn(line)]

  # create or update a file (NOTE: can also be used to replace a file's original content)
  def write(file_path, new_content, mode = "w"):
    return __file_handler(file_path, mode, lambda wf: wf.write(new_content))

  # delete a file (if it exists)
  def delete(file_path):
    return os.remove() if os.path.isfile(file_path) else None

Sie würden dann die FileIO.linesFunktion wie folgt verwenden:

file_ext_lines = FileIO.lines("./path/to/file.ext"):
for i, line in enumerate(file_ext_lines):
  print("Line {}: {}".format(i + 1, line))

Beachten Sie, dass die Parameter mode( "r"standardmäßig) und filter_fn( standardmäßig auf Leerzeilen prüfen) optional sind.

Man könnte sogar die entfernen read, writeund deleteMethoden und die einfach verlassen FileIO.lines, oder sogar in ein separates Verfahren genannt drehen read_lines.

LogicalBranch
quelle
Ist es lines = FileIO.lines(path)wirklich einfacher genug, als with open(path) as f: lines = f.readlines()die Existenz dieses Helfers zu rechtfertigen? Sie sparen beispielsweise 17 Zeichen pro Anruf. (Und die meiste Zeit möchten Sie aus Leistungs- und Speichergründen ein Dateiobjekt direkt durchlaufen, anstatt seine Zeilen trotzdem in eine Liste einzulesen, sodass Sie dies nicht einmal oft verwenden möchten!) Ich bin es Oft ein Fan von kleinen Utility-Funktionen, aber für mich ist es einfach unnötig, eine neue Art zu schreiben, um etwas zu schreiben, das mit der Standardbibliothek bereits kurz und einfach ist.
Mark Amery
Warum sollte man zusätzlich zu dem, was @MarkAmery gesagt hat, eine Klasse dafür verwenden?
AMC
1

Befehlszeilenversion

#!/bin/python3
import os
import sys
abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
filename = dname + sys.argv[1]
arr = open(filename).read().split("\n") 
print(arr)

Laufen Sie mit:

python3 somefile.py input_file_name.txt
jasonleonhard
quelle