Python CSV-Dateien
CSV-Dateien in Python lesen und schreiben mit dem integrierten csv-Modul, einschließlich csv.reader, csv.writer, DictReader und DictWriter mit Praxisbeispielen.
CSV (Comma-Separated Values) ist eines der verbreitetsten Formate zum Austausch von Tabellendaten — jede Tabellenkalkulationsanwendung, jede Datenbank und jedes Data-Science-Tool kann es lesen und schreiben. Das integrierte Python-csv-Modul übernimmt die kniffligen Details automatisch: Es setzt Felder in Anführungszeichen, die Kommas enthalten, gleicht Zeilenumbruch-Eigenheiten verschiedener Betriebssysteme aus und ordnet Zeilen Dictionaries zu. Es muss nichts installiert werden; csv ist in jeder Python-Installation enthalten.
Dieses Kapitel behandelt das Lesen und Schreiben von CSV-Dateien, die Arbeit mit DictReader und DictWriter, den Umgang mit benutzerdefinierten Trennzeichen sowie häufige Fallstricke, die es zu vermeiden gilt.
Was ist eine CSV-Datei?
Eine CSV-Datei ist eine Klartextdatei, in der jede Zeile eine Datenzeile darstellt und die einzelnen Felder durch ein Trennzeichen — in der Regel ein Komma — voneinander getrennt sind. Hier ist ein minimales Beispiel:
name,age,city
Alice,30,New York
Bob,25,LondonDie erste Zeile ist typischerweise ein Header, der die einzelnen Spalten benennt. Die nachfolgenden Zeilen enthalten die eigentlichen Daten. Wenn ein Feldwert selbst ein Komma enthält, wird das Feld in doppelte Anführungszeichen eingeschlossen:
name,bio
Alice,"Engineer, New York"Das csv-Modul verarbeitet diese Anführungszeichenlogik transparent, sodass keine manuelle Verarbeitung erforderlich ist.
CSV-Dateien lesen mit csv.reader
csv.reader verwandelt eine geöffnete Datei (oder einen beliebigen iterierbaren Ausdruck aus Strings) in einen Iterator, der jede Zeile als Python-Liste zurückgibt.
Grundmuster — eine CSV-Datei zeilenweise lesen
import csv
with open("people.csv", newline="") as f:
reader = csv.reader(f)
for row in reader:
print(row)Das Argument newline="" ist wichtig. Ohne es kann Pythons universelle Zeilenumbruchübersetzung unter Windows zusätzliche Leerzeilen einfügen, weil das csv-Modul die Zeilenumbrüche intern selbst verarbeitet.
Wenn people.csv die obigen Beispieldaten enthält, lautet die Ausgabe:
['name', 'age', 'city']
['Alice', '30', 'New York']
['Bob', '25', 'London']Beachten Sie, dass alle Werte — einschließlich der Zahl 30 — als Strings zurückgegeben werden. Das csv-Modul leitet keine Datentypen ab; konvertieren Sie die Werte bei Bedarf selbst.
Die Kopfzeile überspringen
Wenn nur die Datenzeilen und nicht die Kopfzeile benötigt werden, rufen Sie einmal next() auf dem Reader auf, um die erste Zeile zu verbrauchen:
Kopfzeile mit next() überspringen
import csv
with open("people.csv", newline="") as f:
reader = csv.reader(f)
header = next(reader) # consume and store the header
print("Columns:", header)
for row in reader: # only data rows remain
name, age, city = row
print(f"{name} is {age} years old and lives in {city}.")Ausgabe:
Columns: ['name', 'age', 'city']
Alice is 30 years old and lives in New York.
Bob is 25 years old and lives in London.Alle Zeilen in eine Liste laden
Wenn die gesamte Datei auf einmal im Speicher benötigt wird, übergeben Sie den Reader an list():
import csv
with open("people.csv", newline="") as f:
reader = csv.reader(f)
rows = list(reader)
print(rows[0]) # header row
print(rows[1]) # first data rowAusgabe:
['name', 'age', 'city']
['Alice', '30', 'New York']CSV-Dateien schreiben mit csv.writer
csv.writer schreibt Zeilen in ein beliebiges dateiähnliches Objekt und setzt dabei automatisch Felder in Anführungszeichen, die das Trennzeichen, doppelte Anführungszeichen oder Zeilenumbrüche enthalten.
Zeilen in eine neue CSV-Datei schreiben
import csv
rows = [
["product", "price", "quantity"],
["Apple", 1.2, 50],
["Banana", 0.5, 100],
["Cherry", 3.0, 30],
]
with open("inventory.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerows(rows)Nach der Ausführung enthält inventory.csv:
product,price,quantity
Apple,1.2,50
Banana,0.5,100
Cherry,3.0,30Verwenden Sie writer.writerow(row), um eine einzelne Zeile zu schreiben, oder writer.writerows(rows), um mehrere auf einmal zu schreiben. Beide akzeptieren beliebige Iterables.
Warum newline="" beim Schreiben wichtig ist
Unter Windows öffnet Python Textdateien in einem Modus, der \n in \r\n übersetzt. Das csv-Modul schreibt standardmäßig ebenfalls \r\n-Zeilenenden. Zusammen ergibt das \r\r\n — eine Leerzeile zwischen jeder Zeile, wenn die Datei in einem anderen Programm geöffnet wird. Die Angabe von newline="" unterdrückt die zusätzliche Übersetzung und lässt csv die Zeilenenden selbst verwalten.
CSV-Dateien lesen mit csv.DictReader
DictReader ordnet jede Zeile einem OrderedDict (oder einem einfachen dict in Python 3.8+) zu, das nach den Spaltennamen in der Kopfzeile geordnet ist. Dies ist der bevorzugte Ansatz, wenn Spalten aussagekräftige Namen haben und man auf diese per Name statt per Index zugreifen möchte.
Eine CSV-Datei als Folge von Dictionaries lesen
import csv
with open("people.csv", newline="") as f:
reader = csv.DictReader(f)
for row in reader:
print(row["name"], "—", row["city"])Ausgabe:
Alice — New York
Bob — LondonDictReader liest die erste Zeile automatisch als Header. Dies kann durch die Übergabe eines fieldnames-Arguments überschrieben werden:
import csv
# File has no header; provide field names explicitly
with open("data_no_header.csv", newline="") as f:
reader = csv.DictReader(f, fieldnames=["name", "age", "city"])
for row in reader:
print(row)Das Attribut reader.fieldnames enthält stets die Liste der verwendeten Spaltennamen, was bei der Untersuchung vor der Zeilenverarbeitung nützlich ist.
CSV-Dateien schreiben mit csv.DictWriter
DictWriter ist das Gegenstück zu DictReader. Die Spaltennamen werden vorab angegeben, dann werden Dictionaries geschrieben — der Writer ordnet jeden Schlüssel der richtigen Spalte zu.
Eine Liste von Dictionaries in eine CSV-Datei schreiben
import csv
people = [
{"name": "Alice", "age": 30, "city": "New York"},
{"name": "Bob", "age": 25, "city": "London"},
]
fieldnames = ["name", "age", "city"]
with open("people_out.csv", "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader() # writes the column-name row
writer.writerows(people)Die resultierende Datei:
name,age,city
Alice,30,New York
Bob,25,Londonwriteheader() verwendet die beim Erstellen übergebene fieldnames-Liste. Der Aufruf erfolgt einmalig vor allen writerow()-Aufrufen.
Umgang mit zusätzlichen oder fehlenden Schlüsseln
Standardmäßig wirft DictWriter einen ValueError, wenn ein Dictionary einen Schlüssel enthält, der nicht in fieldnames enthalten ist. Dieses Verhalten lässt sich mit dem Parameter extrasaction ändern:
writer = csv.DictWriter(f, fieldnames=fieldnames, extrasaction="ignore")Umgekehrt schreibt der Writer einen leeren String für ein fehlendes Feld, es sei denn, ein restval-Standardwert wird angegeben:
writer = csv.DictWriter(f, fieldnames=fieldnames, restval="N/A")Benutzerdefinierte Trennzeichen und Anführungszeichen
CSV-Dateien in der Praxis sind nicht immer durch Kommas getrennt. Tabulatorgetrennte Werte (TSV) und durch Pipe-Zeichen getrennte Dateien sind verbreitet. Verwenden Sie den Parameter delimiter, um damit umzugehen:
Eine tabulatorgetrennte Datei lesen
import csv
with open("scores.tsv", newline="") as f:
reader = csv.reader(f, delimiter="\t")
for row in reader:
print(row)Eine durch Pipe-Zeichen getrennte Datei schreiben
import csv
with open("output.psv", "w", newline="") as f:
writer = csv.writer(f, delimiter="|")
writer.writerow(["id", "name", "score"])
writer.writerow([1, "Alice", 98])
writer.writerow([2, "Bob", 87])Ausgabedatei:
id|name|score
1|Alice|98
2|Bob|87Anführungszeichen-Konstanten
Der Parameter quoting steuert, welche Felder in der Ausgabe in Anführungszeichen gesetzt werden:
| Konstante | Wert | Verhalten |
|---|---|---|
csv.QUOTE_MINIMAL | 0 | Nur Felder in Anführungszeichen setzen, die das Trennzeichen, das Anführungszeichen selbst oder einen Zeilenumbruch enthalten (Standard) |
csv.QUOTE_ALL | 1 | Jedes Feld in Anführungszeichen setzen |
csv.QUOTE_NONNUMERIC | 2 | Alle nicht-numerischen Felder in Anführungszeichen setzen; der Reader konvertiert felder ohne Anführungszeichen zu float |
csv.QUOTE_NONE | 3 | Niemals Anführungszeichen setzen; Fehler auslösen, wenn das Trennzeichen in einem Feld vorkommt |
Jedes Feld in Anführungszeichen setzen erzwingen
import csv, io
output = io.StringIO()
writer = csv.writer(output, quoting=csv.QUOTE_ALL)
writer.writerow(["name", "bio"])
writer.writerow(["Alice", "Engineer, New York"])
print(output.getvalue())Ausgabe:
"name","bio"
"Alice","Engineer, New York"io.StringIO für CSV im Arbeitsspeicher verwenden
Wenn kein Zugriff auf das Dateisystem nötig ist — etwa in Tests oder bei der Verarbeitung von CSV-Daten aus einer API — kann io.StringIO als dateiähnliches Objekt verwendet werden:
CSV aus einem String verarbeiten
import csv
import io
raw = "name,score\nAlice,95\nBob,87\n"
reader = csv.DictReader(io.StringIO(raw))
for row in reader:
print(row["name"], "scored", row["score"])Ausgabe:
Alice scored 95
Bob scored 87Häufige Fallstricke
Alle Werte sind Strings
csv.reader und DictReader geben stets Strings zurück. Werte müssen explizit konvertiert werden:
age = int(row["age"])
price = float(row["price"])Kodierungsprobleme
Dateien müssen mit der richtigen Kodierung geöffnet werden, um UnicodeDecodeError zu vermeiden. UTF-8 ist die häufigste Kodierung für moderne CSV-Dateien, aber aus Excel exportierte Dateien verwenden möglicherweise latin-1 oder cp1252:
with open("data.csv", newline="", encoding="utf-8") as f:
reader = csv.reader(f)Leerzeilen
Wenn eine CSV-Datei Leerzeilen zwischen Datenzeilen enthält, gibt csv.reader dafür leere Listen [] zurück. Diese lassen sich herausfiltern:
import csv
with open("data.csv", newline="") as f:
reader = csv.reader(f)
for row in reader:
if not row: # skip blank lines
continue
print(row)Fehlerbehandlung
Dateioperationen sollten in einem try/except-Block gekapselt werden, um fehlende Dateien und Berechtigungsfehler sauber abzufangen:
import csv
try:
with open("data.csv", newline="") as f:
reader = csv.reader(f)
for row in reader:
print(row)
except FileNotFoundError:
print("Error: data.csv was not found.")
except PermissionError:
print("Error: no permission to read data.csv.")csv vs. Pandas für große Dateien
Das csv-Modul ist ideal für:
- Kleine bis mittlere Dateien (bis zu einigen hundert MB)
- Skripte, bei denen Pandas nicht installiert ist
- Situationen, in denen eine feinkörnige Kontrolle über das Lesen und Schreiben benötigt wird
Für große Datensätze, komplexes Filtern oder Aggregationsoperationen bietet die Drittanbieter-Bibliothek pandas die Funktionen pd.read_csv() und DataFrame.to_csv(), die deutlich schneller und funktionsreicher sind.
Alles zusammen
Das folgende Beispiel liest eine CSV-Datei, filtert Zeilen anhand einer Bedingung und schreibt die gefilterten Ergebnisse in eine neue Datei:
Zeilen filtern und eine neue CSV-Datei schreiben
import csv
input_file = "inventory.csv"
output_file = "expensive.csv"
with open(input_file, newline="") as infile, \
open(output_file, "w", newline="") as outfile:
reader = csv.DictReader(infile)
writer = csv.DictWriter(outfile, fieldnames=reader.fieldnames)
writer.writeheader()
for row in reader:
if float(row["price"]) >= 1.0:
writer.writerow(row)
print(f"Filtered rows written to {output_file}.")Dieses Muster — beide Dateien im selben with-Block öffnen, Zeilen vom Reader zum Writer streamen — verarbeitet Dateien beliebiger Größe, ohne alles auf einmal in den Speicher zu laden.
Verwandte Kapitel
- Python-Dateiverarbeitung — Öffnen, Lesen und Schreiben von Klartextdateien
- Python-Dateien lesen — Dateiinhalte mit
read()undreadlines()lesen - Python-Dateien schreiben und erstellen — Dateien schreiben und ergänzen
- Python JSON — Arbeiten mit JSON, einem weiteren verbreiteten Datenaustauschformat
- Python Try Except — Datei-nicht-gefunden- und andere Ausnahmen behandeln