Zum Inhalt springen
aviral gupta

// I4.5 · ca. 30 Min. · Aufbau

CSV-Dateien

Nach dieser Lektion lesen und schreiben Sie CSV-Dateien mit dem Modul csv, auch mit Feldern in Anführungszeichen, Kopfzeilen und den Semikolon-Dateien deutscher Tabellenprogramme.

Lektion 5 von 6 in I4 Die Standardbibliothek für echte Programme

Danach können Sie

  • CSV-Dateien mit csv.reader und DictReader lesen, mit newline="" geöffnet, und die Felder selbst umwandeln
  • CSV-Dateien mit csv.writer und DictWriter schreiben und vorhersagen, welche Felder Anführungszeichen bekommen
  • Andere Dialekte lesen und schreiben, etwa delimiter=";" für deutsches Excel
  1. Aufwärmen · Aufgabe 1 von 7

    Aufwärmen mit String-Methoden: eine CSV-Zeile mit einem Feld in Anführungszeichen. Was gibt das aus?

    print('"Berlin, Mitte",5'.split(","))
  2. Vorhersagen · Aufgabe 2 von 7

    Sagen Sie es voraus, bevor Sie weiterlesen. io.StringIO steht hier für eine Datei. Was gibt das aus?

    import csv
    import io
    
    data = io.StringIO("name,age\nAda,36\n")
    rows = list(csv.DictReader(data))
    print(rows[0]["age"] + "1")
  3. Üben · Aufgabe 3 von 7

    Ergänzen Sie das Argument, mit dem jede CSV-Datei geöffnet werden sollte, zum Lesen wie zum Schreiben.

    with open("out.csv", "w", ____="", encoding="utf-8") as f:
    open("out.csv", "w", ="", encoding="utf-8")
  4. Üben · Aufgabe 4 von 7

    Wie speichert der Writer diese drei Felder? Was gibt das aus?

    import csv
    import io
    
    buffer = io.StringIO()
    csv.writer(buffer).writerow(["Berlin, Mitte", 5, 'say "hi"'])
    print(buffer.getvalue(), end="")
  5. Üben · Aufgabe 5 von 7

    Ordnen Sie jedem Teil des Moduls csv zu, was er tut.

  6. Denksport · Aufgabe 6 von 7

    Knobelaufgabe. Die Datei hat eine Kopfzeile, und das Programm übergibt zusätzlich fieldnames. Was gibt das aus?

    import csv
    import io
    
    data = io.StringIO("name,points\nAda,3\nBo,5\n")
    rows = list(csv.DictReader(data, fieldnames=["name", "points"]))
    print(len(rows), rows[0]["points"])
  7. Anwenden · Aufgabe 7 von 7

    Kleine Aufgabe. Schreiben Sie exam.csv mit der Kopfzeile name,points und drei Zeilen: Ada 72, Bo 45 und Cy 50. Schreiben Sie dann ein Programm, das jede Zeile mit mindestens 50 Punkten nach passed.csv kopiert, mit derselben Kopfzeile. Geben Sie zur Kontrolle repr des Textes der neuen Datei aus.

    Prüfen Sie Ihr Ergebnis anhand dieser Liste

Selbst programmieren

Lesen Sie das ausgearbeitete Beispiel und lösen Sie dann die Übungen. Ihr Code läuft in Ihrem Browser oder auf Ihrem Computer und wird nie hochgeladen.

Ausgearbeitetes Beispiel

Ausgaben rein, eine Übersicht für Excel raus

expenses.csv (zweiter Tab) enthält vier Ausgaben; zwei Beschreibungen enthalten ein Komma oder Anführungszeichen. Das Programm liest die Datei mit DictReader, gibt jede Zeile aus und summiert die Beträge je Kategorie. Dann schreibt es summary.csv für ein deutsches Tabellenprogramm, mit Semikolons und Dezimalkomma, und gibt den rohen Text dieser Datei aus.

main.py

import csv

totals: dict[str, float] = {}
with open("expenses.csv", newline="", encoding="utf-8") as f:
    for row in csv.DictReader(f):
        totals[row["category"]] = totals.get(row["category"], 0.0) + float(row["amount"])
        print(f"{row['date']}  {row['description']:<13} {row['amount']:>6}")

# A summary for a German spreadsheet: semicolons and a decimal comma.
with open("summary.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=["category", "total"], delimiter=";")
    writer.writeheader()
    for category, total in sorted(totals.items()):
        writer.writerow({"category": category, "total": f"{total:.2f}".replace(".", ",")})

with open("summary.csv", newline="", encoding="utf-8") as f:
    print(repr(f.read()))

expenses.csv

date,category,description,amount
2026-09-01,food,"Bread, butter",4.20
2026-09-02,transport,Train ticket,12.90
2026-09-03,food,Coffee,3.10
2026-09-05,home,"Lamp ""Luna""",24.99

Ausführen mit

python main.py

Ausgabe

2026-09-01  Bread, butter   4.20
2026-09-02  Train ticket   12.90
2026-09-03  Coffee          3.10
2026-09-05  Lamp "Luna"    24.99
'category;total\r\nfood;7,30\r\nhome;24,99\r\ntransport;12,90\r\n'
  • "Bread, butter" kam als ein Feld zurück, ohne seine Anführungszeichen.
  • Die verdoppelten Anführungszeichen in "Lamp ""Luna""" wurden als je eines gelesen.
  • float(row["amount"]) wandelt den Text vor dem Addieren um: Der Reader liefert nur Strings.
  • Mit delimiter=";" brauchen die Dezimalkommas in 7,30 keine Anführungszeichen.
Ändern und ausführen

Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.

Beim ersten Ausführen lädt Ihr Browser Python herunter (bis zu 6.5 MB) und speichert es im Cache. Ihr Code bleibt auf Ihrem Gerät.

Übungen

Übung 1 von 2

Punkte addieren

scores.csv (zweiter Tab) hat die Spalten name und points, und ein Name kann mehrmals vorkommen. Schreiben Sie load_scores(path), das ein dict von jedem Namen auf seine Gesamtpunkte liefert, als int. Die Namen enthalten Kommas, daher scheitert split(",") im Startcode. Nutzen Sie das Modul csv; die Tests probieren auch eine Datei mit vertauschten Spalten.

Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.

Beim ersten Ausführen lädt Ihr Browser Python herunter (bis zu 6.5 MB) und speichert es im Cache. Ihr Code bleibt auf Ihrem Gerät.

Hinweise
  1. Hinweis 1

    Öffnen Sie die Datei mit newline="" und encoding="utf-8" und laufen Sie über csv.DictReader(f).

  2. Hinweis 2

    Jede Zeile ist ein dict mit den Schlüsseln name und points, egal in welcher Spaltenreihenfolge.

  3. Hinweis 3

    row["points"] ist ein String: Addieren Sie int(row["points"]) zur Summe für row["name"].

Eine Lösung zeigen

Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.

import csv


def load_scores(path: str) -> dict[str, int]:
    totals: dict[str, int] = {}
    with open(path, newline="", encoding="utf-8") as f:
        for row in csv.DictReader(f):
            name = row["name"]
            totals[name] = totals.get(name, 0) + int(row["points"])
    return totals


if __name__ == "__main__":
    print(load_scores("scores.csv"))
Auf dem eigenen Computer ausführen

Installieren Sie Python 3.14 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.

main.py

def load_scores(path: str) -> dict[str, int]:
    totals: dict[str, int] = {}
    with open(path, encoding="utf-8") as f:
        next(f)  # skip the header
        for line in f:
            name, points = line.strip().split(",")
            totals[name] = totals.get(name, 0) + int(points)
    return totals


if __name__ == "__main__":
    print(load_scores("scores.csv"))

test_main.py

from main import load_scores


def write(path, text):
    with open(path, "w", newline="", encoding="utf-8") as f:
        f.write(text)


def test_given_file():
    """Die gegebene Datei ergibt 7 Punkte für Ada und 5 für Grace"""
    got = load_scores("scores.csv")
    assert got == {"Lovelace, Ada": 7, "Hopper, Grace": 5}, f"load_scores lieferte {got!r}"


def test_other_column_order():
    """Spalten in anderer Reihenfolge werden über den Namen gelesen"""
    write("t_order.csv", "points,name\n2,Bo\n3,Bo\n")
    got = load_scores("t_order.csv")
    assert got == {"Bo": 5}, f"bei points,name lieferte die Funktion {got!r}"


def test_header_only():
    """Eine Datei nur mit Kopfzeile ergibt {}"""
    write("t_empty.csv", "name,points\n")
    got = load_scores("t_empty.csv")
    assert got == {}, f"bei einer Datei nur mit Kopfzeile lieferte die Funktion {got!r}"

scores.csv

name,points
"Lovelace, Ada",3
"Hopper, Grace",5
"Lovelace, Ada",4

Unter macOS und Linux tippen Sie python3, wo in diesen Befehlen python steht, wie in der ersten Lektion.

Programm ausführen:

python main.py

Prüfungen ausführen (learnrun.py muss im selben Ordner liegen):

python learnrun.py test
learnrun.py herunterladen

Übung 2 von 2

Export für deutsches Excel

Schreiben Sie export_semicolon(src, dst). Die Funktion liest die kommagetrennte Datei src und schreibt dieselben Zeilen samt Kopfzeile nach dst, mit Semikolons als Trennzeichen. Sie liefert die Zahl der Datenzeilen, ohne Kopfzeile. Ein Feld mit Semikolon muss ein Feld bleiben. replace(",", ";") im Startcode ändert auch Kommas innerhalb von Feldern.

Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.

Beim ersten Ausführen lädt Ihr Browser Python herunter (bis zu 6.5 MB) und speichert es im Cache. Ihr Code bleibt auf Ihrem Gerät.

Hinweise
  1. Hinweis 1

    Lesen Sie die Zeilen mit csv.reader(f) aus einer mit newline="" geöffneten Datei.

  2. Hinweis 2

    Schreiben Sie sie mit csv.writer(f, delimiter=";").writerows(rows); der Writer setzt Anführungszeichen, wo ein Feld ein ; enthält.

  3. Hinweis 3

    Die Zahl der Datenzeilen ist len(rows) - 1, denn die erste Zeile ist die Kopfzeile.

Eine Lösung zeigen

Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.

import csv


def export_semicolon(src: str, dst: str) -> int:
    with open(src, newline="", encoding="utf-8") as f:
        rows = list(csv.reader(f))
    with open(dst, "w", newline="", encoding="utf-8") as f:
        csv.writer(f, delimiter=";").writerows(rows)
    return len(rows) - 1


if __name__ == "__main__":
    with open("people.csv", "w", newline="", encoding="utf-8") as f:
        f.write('name,city\nAda,"Berlin; Mitte"\n')
    print(export_semicolon("people.csv", "people_de.csv"))
Auf dem eigenen Computer ausführen

Installieren Sie Python 3.14 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.

main.py

def export_semicolon(src: str, dst: str) -> int:
    with open(src, encoding="utf-8") as f:
        text = f.read()
    with open(dst, "w", encoding="utf-8") as f:
        f.write(text.replace(",", ";"))
    return 0


if __name__ == "__main__":
    with open("people.csv", "w", newline="", encoding="utf-8") as f:
        f.write('name,city\nAda,"Berlin; Mitte"\n')
    print(export_semicolon("people.csv", "people_de.csv"))

test_main.py

import csv

from main import export_semicolon

SOURCE = 'name,city\nAda,"Berlin; Mitte"\nBo,"Köln, Süd"\n'


def export(text):
    with open("t_src.csv", "w", newline="", encoding="utf-8") as f:
        f.write(text)
    count = export_semicolon("t_src.csv", "t_dst.csv")
    with open("t_dst.csv", newline="", encoding="utf-8") as f:
        return count, f.read()


def test_count():
    """Zwei Datenzeilen ergeben 2"""
    count, text = export(SOURCE)
    assert count == 2, f"export_semicolon lieferte {count!r}, erwartet war 2"


def test_round_trip():
    """Mit delimiter=';' zurückgelesen, sind die Zeilen unverändert"""
    count, text = export(SOURCE)
    with open("t_dst.csv", newline="", encoding="utf-8") as f:
        rows = list(csv.reader(f, delimiter=";"))
    want = [["name", "city"], ["Ada", "Berlin; Mitte"], ["Bo", "Köln, Süd"]]
    assert rows == want, f"die neue Datei mit delimiter=';' gelesen ergab {rows!r}"


def test_file_text():
    """Die Datei nutzt ; und \\r\\n und fasst nur das Feld mit ; ein"""
    count, text = export(SOURCE)
    want = 'name;city\r\nAda;"Berlin; Mitte"\r\nBo;Köln, Süd\r\n'
    assert text == want, f"die neue Datei enthält {text!r}"

Unter macOS und Linux tippen Sie python3, wo in diesen Befehlen python steht, wie in der ersten Lektion.

Programm ausführen:

python main.py

Prüfungen ausführen (learnrun.py muss im selben Ordner liegen):

python learnrun.py test
learnrun.py herunterladen

Häufige Fehler

Strings addieren

import csv
import io

data = io.StringIO("item,amount\nbread,4\ncoffee,3\n")
print(sum(row["amount"] for row in csv.DictReader(data)))

Was Python ausgibt

TypeError: unsupported operand type(s) for +: 'int' and 'str'

Warum, und die Lösung

Das Modul csv liefert jedes Feld als String, und sum beginnt bei 0, einem int. Wandeln Sie jeden Wert um: sum(int(row["amount"]) for row in ...), oder float() für Beträge mit Nachkommastellen.

Ein Schlüssel, der nicht in fieldnames steht

import csv
import io

writer = csv.DictWriter(io.StringIO(), fieldnames=["name"])
writer.writerow({"name": "Ada", "age": 36})

Was Python ausgibt

ValueError: dict contains fields not in fieldnames: 'age'

Warum, und die Lösung

DictWriter schreibt genau die Spalten in fieldnames und lehnt ein dict mit anderen Schlüsseln ab, damit keine Daten unbemerkt verloren gehen. Nehmen Sie den Schlüssel in fieldnames auf, oder übergeben Sie extrasaction="ignore", wenn er wirklich wegfallen soll.

Eine Semikolon-Datei mit dem Standarddialekt lesen

import csv
import io

data = io.StringIO("name;points\nAda;3\n")
for row in csv.DictReader(data):
    print(row["points"])

Was Python ausgibt

KeyError: 'points'

Warum, und die Lösung

Ohne delimiter=";" ist die ganze Zeile name;points ein einziger Feldname, einen Schlüssel points gibt es also nicht. Dateien aus deutschem Excel nutzen meist Semikolons: Übergeben Sie DictReader delimiter=";". print(row) zeigt, wie die Schlüssel wirklich heißen.

Python im Browser: Pyodide 314.0.7, MPL-2.0. Lizenz und Quellcode

Abschlussquiz

5 Fragen, ohne Hinweise. Ab 80 % ist die Lektion abgeschlossen.

Erledigen Sie zuerst alle Aufgaben oben, um das Abschlussquiz freizuschalten.

Problem melden

Etwas ist falsch oder unklar? Beschreiben Sie es kurz, dann wird es geprüft und korrigiert.

#

Mindestens 20 Zeichen.

Nur, wenn Sie eine Antwort wünschen.

Kernideen

Warum nicht split(",")

Ein CSV-Feld darf ein Komma, ein Anführungszeichen oder sogar einen Zeilenumbruch enthalten, solange es in doppelten Anführungszeichen steht: "Berlin, Mitte". split(",") zerschneidet ein solches Feld; das Modul csv liest es richtig. Öffnen Sie die Datei mit newline="" und einer Kodierung und laufen Sie über csv.reader(f): Jede Zeile ist eine Liste von Strings. csv.DictReader(f), das Sie aus dem I3-Build kennen, nimmt die erste Zeile als Feldnamen und liefert jede weitere Zeile als dict. Jeder Wert ist ein String, Zahlen wandeln Sie also selbst mit int() oder float() um.

Zeilen schreiben

csv.writer(f).writerow(["Ada", 36]) schreibt eine Zeile, writerows mehrere. csv.DictWriter(f, fieldnames=[...]) schreibt dicts: Rufen Sie einmal writeheader() für die Kopfzeile auf, dann writerow(row). Ein Schlüssel, der nicht in fieldnames steht, löst ValueError aus; ein fehlender wird als leeres Feld geschrieben. Der Writer setzt ein Feld nur in Anführungszeichen, wenn nötig, also wenn es das Trennzeichen, ein Anführungszeichen oder einen Zeilenumbruch enthält, und verdoppelt Anführungszeichen darin: say "hi" wird zu "say ""hi""". Zeilen enden mit \r\n.

Dialekte: andere Trennzeichen

Der Standarddialekt excel trennt mit Kommas. Deutsches Excel speichert CSV mit Semikolons, weil das Komma dort das Dezimaltrennzeichen ist. Geben Sie reader, writer, DictReader und DictWriter delimiter=";" mit, um solche Dateien zu lesen und zu schreiben. Mit dem falschen Trennzeichen gelesen, kommt jede Zeile als ein einziges Feld zurück. Öffnen Sie immer mit newline="": Das Modul csv behandelt Zeilenenden selbst, und ohne diese Angabe werden Umbrüche in Feldern mit Anführungszeichen falsch gelesen, und unter Windows landet in jeder Zeile ein zusätzliches \r.

Quellen

Zuletzt geprüft am 29. September 2026