Der komplette Guide zum CSV-Dateien lesen mit Python

Inhalt
    Fügen Sie eine Überschrift hinzu, um mit der Erstellung des Inhaltsverzeichnisses zu beginnen

    CSV-Dateien begegnen dir an jeder Ecke. Egal, ob beim Export aus Excel, verarbeiten von Log-Dateien, Datenaustausch zwischen Systemen oder auch einfach der Download deiner Banktransaktionen. Mit Python hast du ein hervorragendes Werkzeug an der Hand, um diese Daten schnell und effizient einzulesen und weiterzuverarbeiten.

    In diesem Guide zeige ich dir das Python-Standardmodul “csv”, mit dem du – ganz ohne Installation – sofort loslegen kannst. Dabei werden wir alles Wichtige abdecken: vom Öffnen der Datei über den Umgang mit verschiedenen Trennzeichen, bis hin zur Behandlung typischer Stolpersteine. Am Ende werfen wir noch einen Blick auf Alternativen, die Python dir für komplexere Aufgaben zur Verfügung stellt.

    Ziel: Nach diesem Artikel kannst du CSV-Dateien zuverlässig in Python einlesen und kennst die wichtigsten Optionen für deine Datenverarbeitung.

    Bereit loszulegen? 

    (Möchtest du die Python-Grundlagen von Anfang an richtig lernen? Hol dir jetzt die kostenlosen Start-Kapitel meines E-Books ‚Python Basics‘!)

    CSVs einlesen mit dem csv-Modul

    Vorbereitung: Unsere Beispiel-CSV

    Damit die folgenden Code-Beispiele nachvollziehbar sind, gehen wir von einer CSV-Datei namens adressen.csv mit folgendem beispielhaften Inhalt aus:

    Vorname,Nachname,Strasse,Hausnummer,PLZ,Ort,Email
    Ingo,Janssen,Musterstraße,1,12345,Musterstadt,ingo@beispiel.de
    Dietmar,Köhler,Testweg,5,54321,Testhausen,dietmar@beispiel.de
    Erika,Mustermann,Beispielallee,10,98765,Beispielburg,erika@beispiel.de

    Schritt 1: Die CSV-Datei korrekt öffnen

    Der erste Schritt ist immer, die Datei zu öffnen. Dafür nutzen wir in Python am besten das with open()-Statement. Es sorgt dafür, dass die Datei nach der Benutzung auch sicher wieder geschlossen wird, selbst wenn Fehler auftreten.

    import csv
    from pathlib import Path
    
    datei_pfad = Path('daten/adressen.csv')
    
    try:
        with open(datei_pfad, 'r', encoding='utf-8', newline='') as csv_datei:
            # --- Hier kommt der Code zum Lesen rein (siehe nächste Schritte) ---
            print(f"Datei '{datei_pfad}' erfolgreich geöffnet.")
    except FileNotFoundError:
        print(f"FEHLER: Die Datei '{datei_pfad}' wurde nicht gefunden.")
        # Hier kannst du auf den Fehler reagieren, wenn du möchtest

    Was passiert hier genau?

    • from pathlib import Path: Wir importieren die Path-Klasse für eine moderne und betriebssystemunabhängige Art, mit Dateipfaden umzugehen.
    • datei_pfad = Path('daten/adressen.csv'): Hier erstellen wir ein Path-Objekt, dem wir den Pfad zu unserer CSV-Datei übergeben. Die Datei liegt in dem Ordner “daten”. Daraus ergibt sich der Pfad: daten/adressen.csv. Wenn dein Pfad abweichend ist, musst du ihn hier entsprechend anpassen. pathlib, also das Path-Objekt, kümmert sich dann darum, die Pfade richtig aufzulösen. Egal, ob du unter Windows, MacOS oder Linux arbeitest.
    • open(datei_pfad, 'r', ...): Jetzt übergeben das Path-Objekt an open. Anschließend geben wir mit ‚r‘ noch den Modus an, damit Python weiß, was es mit der Datei machen soll. Das ‚r‘ steht für read (lesen). In der verlinkten Dokumentation kannst du noch mehr über die verschiedenen Modi erfahren.
    • encoding='utf-8': Das ist Essentiell! Wenn du Umlaute oder Sonderzeichen (wie in deutschen Namen oder Adressen) in deiner Datei hast, musst du Python mitteilen, dass der Inhalt als ‚utf-8‘ interpretiert werden soll. UTF-8 ist heutzutage auch der Standard.
    • newline='': Wenn du mit open() eine Datei öffnest, werden Standard Zeilenumbrüche (\n, \r, \r\n) automatisch als neue Zeile interpretiert. Das csv-Modul versucht allerdings selbstständig zu interpretieren, wann in deiner CSV-Datei tatsächlich eine neue Zeile beginnt. Hast du zum Beispiel in einer Spalte in der CSV-Datei einen längeren Text, der einen Zeilenumbruch enthält, würde das open() den auch als Zeilenumbruch werten und das csv-Modul kann nicht mehr korrekt einlesen. Deswegen ist dieser Parameter ist entscheidend bei der Arbeit mit dem csv-Modul! Er verhindert, dass Python die Zeilenenden selbst interpretiert und das csv-Modul dadurch durcheinanderkommt. Immer setzen! 
    • as csv_datei: Damit geben wir dem geöffneten Datei-Objekt einfach nur einen Namen, damit wir später im with-Block komfortabel darauf zugreifen können.
    • try...except FileNotFoundError: Ein try…except macht genau das, was es sagt. Es versucht (try) den code in dem Block auszuführen. Kommt es zu einem Fehler, bzw. einer Ausnahme (except), überspringt die Ausführung den restlichen Code in dem Block und springt direkt in den except-Block, um den Fehler zu behanden. Der häufigste Fehler ist, dass die Datei am angegebenen Pfad gar nicht existiert (FileNotFoundError). Den Fehler fangen wir hier ab und geben eine ordentliche, klare Fehlermeldung aus.

    Schritt 2: Zeilen als Listen lesen mit csv.reader

    Nachdem die Datei offen ist, brauchen wir ein Werkzeug, das die CSV-Struktur versteht: den csv.reader.

    import csv
    from pathlib import Path
    
    datei_pfad = Path('daten/adressen.csv')
    
    try:
        with open(datei_pfad, 'r', encoding='utf-8', newline='') as csv_datei:
            reader = csv.reader(csv_datei, delimiter=',')
            print(f"Datei '{datei_pfad}' erfolgreich geöffnet.")
            print("Daten aus der CSV-Datei:")
    
            for zeile in reader:
                # Möglichkeit 1: Ganze Zeile als Liste ausgeben
                print(zeile)
                # Möglichkeit 2: Da jede Zeile eine Liste ist, kannst du auch per Index direkt auf die Daten zugreifen
                if len(zeile) >= 7: # Sicherstellen, dass genug Spalten vorhanden sind
                    print("-" * 20) # Optischer Trenner
                    print(f'Vorname: {zeile[0]}')
                    print(f'Nachname: {zeile[1]}')
                    print(f'Straße: {zeile[2]}')
                    print(f'Hausnummer: {zeile[3]}')
                    print(f'Postleitzahl: {zeile[4]}')
                    print(f'Ort: {zeile[5]}')
                    print(f'E-Mail: {zeile[6]}')
                    print("-" * 20) # Optischer Trenner
    except FileNotFoundError:
        print(f"FEHLER: Die Datei '{datei_pfad}' wurde nicht gefunden.")
        # Hier kannst du auf den Fehler reagieren, wenn du möchtest
    except IndexError:
        print(f"FEHLER: Eine Zeile in '{datei_pfad}' hat weniger Spalten als erwartet.")

    Erklärung:

    • reader = csv.reader(csv_datei, delimiter=','): Wir erstellen das reader-Objekt und übergeben ihm das Datei-Objekt (csv_datei). Mit delimiter legen wir das Trennzeichen fest. Achtung: Unsere Beispieldatei oben nutzt ein Komma (,), viele deutsche CSVs nutzen aber ein Semikolon (;). Passe den delimiter hier unbedingt an deine Datei an!
    • for zeile in reader: Der reader ist iterierbar. Das heißt, wir können ihn direkt in einer for-Schleife verwenden, um Zeile für Zeile durch die Datei zu gehen.
    • print(zeile): Jede zeile, die der reader liefert, also jeder Zeiler in deiner CSV-Datei, wird als Liste von Strings zur Verfügung gestellt. Jeder Eintrag in der Liste entspricht also einer Zelle in deiner CSV-Datei.
    • zeile[0]: Da zeile eine Liste ist, können wir mit dem Index (Ein Index beginnt immer bei 0) auf einzelne Zellen zugreifen (z.B. zeile[0] für die erste Spalte „Vorname“, zeile[1] für „Nachname“ usw.).

    Schritt 3: Mit verschiedenen Trennzeichen und Dialekten umgehen

    Wie schon in Schritt 2 erwähnt, ist das Trennzeichen (delimiter) in CSV-Dateien nicht immer ein Komma, auch wenn der Name „Comma Separated Values“ das suggeriert. Gerade bei uns, im deutschen Raum, ist das Semikolon (;) sehr verbreitet, aber auch Tabulatoren (\t) oder andere Zeichen sind möglich. Der Fantasie sind hier kaum Grenzen gesetzt. Ich “durfte” schon so einiges sehen.

    Zum Glück ist das csv.reader-Objekt flexibel und kann mit vielem umgehen, was du ihm entgegen wirfst, zumindest, solange du über den delimiter mitteilst, welches Zeichen du genau verwendst:

    import csv
    from pathlib import Path
    
    datei_pfad_semikolon = Path('daten/adressen_semikolon.csv')
    datei_pfad_tab = Path('daten/adressen_tab.csv')
    
    try:
       # Mit Semicolon als Trennzeichen
        with open(datei_pfad_semikolon, 'r', encoding='utf-8', newline='') as csv_datei:
            reader_semi = csv.reader(csv_datei, delimiter=';')
            print(f"\n--- Lese '{datei_pfad_semikolon}' mit Semikolon ---")
            for zeile in reader_semi:
                print(zeile)
        # Mit Tabulator als Trennzeichen
        with open(datei_pfad_tab, 'r', encoding='utf-8', newline='') as csv_datei:
            # '\t' ist ein escape character, der für einen Tabulator steht
            reader_tab = csv.reader(csv_datei, delimiter='\t')
            print(f"\n--- Lese '{datei_pfad_tab}' mit Tabulator ---")
            for zeile in reader_tab:
                print(zeile)
    except FileNotFoundError as e:
        print(f"FEHLER: Datei nicht gefunden - {e}")
    except csv.Error as e:
        print(f"FEHLER beim Lesen der CSV: {e}")
    except IndexError:
        print(f"FEHLER: Eine Zeile hat weniger Spalten als erwartet.")

    Was, wenn das Trennzeichen in einem Feld vorkommt?

    Auch das kann natürlich passieren. Du weisst nie, was für Daten eingetragen wurden. Zum Beispiel kann eine Adresse ein Komma enthalten, obwohl das Komma eigentlich das Trennzeichen in deiner CSV-Datei sein soll. Genau dafür gibt es die beiden Parameter quotechar und quoting.

    Im Standard, also wenn du nichts angibst, werden doppelte Anführungszeichen („) verwendet, um Felder zu „umschließen“. Der Inhalt einer Zelle ist also nicht nur mit einem speziellen Zeichen von dem nächsten Inhalt getrennt, sondern nochmal von den doppelten Anführungszeichen umschlossen. Damit weiss das csv-Modul, dass alles zwischen den Anführungszeichen einfach nur als Inhalt interpretiert werden soll.

    Hier ein Beispiel, wie so eine Datei aussehen kann (adressen_quotes.csv). Die CSV-Datei hat ein Komma als Delimiter, aber auch Komma in den Daten selbst:

    Vorname,Nachname,Strasse,Hausnummer,PLZ,Ort,Email
    Ingo,Janssen,"Musterstraße, Weg 1",1,12345,Musterstadt,ingo@beispiel.de
    Erika,"Mustermann, geb. Beispiel","Testallee 5",10,98765,Beispielburg,erika@beispiel.de

    Das csv-Modul weiss im Standard schon, wie es mit Anführungszeichen umgehen soll. Felder, die in diesem Zeichen eingeschlossen sind, werden als ein Feld behandelt, auch wenn sie den delimiter enthalten.

    # (Imports und Pfad-Definition wie oben...)
    datei_pfad_quotes = Path('daten/adressen_quotes.csv')
    try:
        with open(datei_pfad_quotes, 'r', encoding='utf-8', newline='') as csv_datei:
            # quotechar ist automatisch das Anführungszeichen, wenn du nichts angibst.
            reader_quotes = csv.reader(csv_datei, delimiter=',')
            print(f"\n--- Lese '{datei_pfad_quotes}' mit Quotes ---")
    
            for zeile in reader_quotes:
                print(zeile)
                # Das ist die erwartete Ausgabe
                # ['Ingo', 'Janssen', 'Musterstraße, Weg 1', '1', '12345', 'Musterstadt', 'ingo@beispiel.de']
    except FileNotFoundError as e:
        print(f"FEHLER: Datei nicht gefunden - {e}")
    except csv.Error as e:
        print(f"FEHLER beim Lesen der CSV: {e}")
    • quotechar: Gibt das Zeichen an, das zum Umschließen von Feldern verwendet wird (Standard: „).
    • quoting: Steuert, wann diese Anführungszeichen berücksichtigt werden. Der Standard (csv.QUOTE_MINIMAL) ist meistens ausreichend (Quotes werden nur beachtet, wenn sie nötig sind, z.B. wegen des Delimiters im Feld). Andere Optionen wie csv.QUOTE_ALL (jedes Feld ist gequotet) oder csv.QUOTE_NONE (Quotes werden ignoriert) sind seltener nötig.

    (Optionaler Hinweis für Fortgeschrittene): Für sehr exotische oder uneinheitliche CSV-Formate gibt es auch den csv.Sniffer. Der versucht das Format, also sowohl Delimiter, als auch Quotechar, automatisch zu erkennen. Das ist aber wirklich nur als letzter Not-Haken zu empfehlen. Die Ergebnisse sind hier in der Regel wenig zuverlässig.

    Schritt 4: Die Kopfzeile überspringen

    Die Kopfzeile zu überspringen ist optional, aber oft ganz nützlich.

    Normalerweise stellt die erste Zeile einer CSV-Datei die Spaltenüberschriften dar. Die Zeile wird auch als “Header” bezeichnet, weil sie eben den “Kopf” der Daten widerspiegelt. Oft interessieren dich die Spaltenüberschriften nur fachlich, nicht technisch. In den Fällen überspringst du die Kopfzeile und arbeitest direkt mit den Daten.

    Wie schon gelernt, ist das reader-Objekt ein Iterator. Man kann also mit einer Schleife Zeile für Zeile durch die Daten laufen. Das heißt, wir können auch kontrollieren, ob wir eine Zeile verarbeiten wollen oder nicht. In einer Schleife kann das über continue gemacht werden. Dann hast du allerdings das Problem prüfen zu müssen, ob es denn die erste Zeile ist, oder nicht. Möchtest du einfach nur die erste Zeile überspringen, hat Python dafür die eingebaute Funktion next().

    next() liefert uns das nächste Element aus dem Iterator (in diesem Fall die erste Zeile, also die Kopfzeile) und „verbraucht“ es gleichzeitig. Die erste Zeile wird also schon zurückgegeben, wie es bei der for Schleife auch der Fall wäre. Der Iterator merkt sich, was er schon verarbeitet hat. Wenn wir danach die for-Schleife starten, weiß der Iterator wo er war und setzt die Verarbeitung an der Stelle fort. Das ist dann die zweite Zeile in der CSV-Datei.

    # (Imports, Pfad-Definition, try-Block wie oben...)
        with open(datei_pfad, 'r', encoding='utf-8', newline='') as csv_datei:
            reader = csv.reader(csv_datei, delimiter=',')
    
            try:
                # Die erste Zeile “verarbeiten” und in einer Variablen speichern
                kopfzeile = next(reader)
                print(f"\nKopfzeile erfolgreich gelesen: {kopfzeile}")
                print("\nNur Datenzeilen:")
    
                # Die Schleife startet jetzt bei der ZWEITEN Zeile
                for zeile in reader:
                    print(zeile)
            except StopIteration:
                # Hast du keine Daten in der Datei, kann next() nichts zurück liefern und wirft diesen Fehler.
                print("FEHLER: Die CSV-Datei ist leer oder enthält nur eine Kopfzeile.")
            except csv.Error as e:
                print(f"FEHLER beim Lesen der CSV nach der Kopfzeile: {e}")

    Mit kopfzeile = next(reader) holen wir uns also die erste Zeile und speichern sie (falls wir die Spaltennamen später brauchen). Danach können wir mit der for-Schleife direkt die Daten Zeile für Zeile verarbeiten. Wir haben der Hydra den „Kopf abgeschlagen“ 😉.

    Schritt 5: Daten weiterverarbeiten – Von Text zu Zahlen

    Bisher haben wir gesehen, dass csv.reader uns jede Zeile als Liste von Strings liefert. Das ist schonmal schön, um den Inhalt zu erhalten. Oft sind aber Dinge enthalten, die als Zahl ausgedrückt, oder für weitere Rechnunge benötigt werden. Zum Beispiel Preisdaten. Oder, um das Eingangsbeispiel aufzugreifen, Banktransaktionen. Du möchtest vielleicht Kategorien bilden und aufsummieren oder Kontostände berechnen. Du musst die eingelesenen Werte also erstmal von Text (Strings) zu Zahlen (z.B. int für Ganzzahlen oder float für Kommazahlen) umwandeln.

    Nehmen wir mal die Spalten mit der Hausnummer und Postleitzahl. Die wollen wir jetzt als Zahlen behandeln:

    # (Imports, Pfad-Definition, try-Block für FileNotFoundError wie oben...)
        with open(datei_pfad, 'r', encoding='utf-8', newline='') as csv_datei:
            reader = csv.reader(csv_datei, delimiter=',')
            try:
                kopfzeile = next(reader)
                print(f"Kopfzeile: {kopfzeile}")
                print("\nVerarbeitete Daten (mit Typumwandlung):")
    
                for zeile in reader:
                    try:
                        vorname = zeile[0]
                        nachname = zeile[1]
                        strasse = zeile[2]
                        # Umwandlung zu Integer (Ganzzahl)
                        hausnummer = int(zeile[3])
                        plz = int(zeile[4])
                        ort = zeile[5]
                        email = zeile[6]
                        # Jetzt kannst du mit den Zahlen arbeiten:
                        if plz > 50000:
                            print(f"{vorname} {nachname} wohnt in einer hohen PLZ-Region ({plz}) in {ort}.")
                    except ValueError:
                        # Fehler bei der Umwandlung (z.B. wenn der Inhalt nicht als Zahl interpretiert werden kann)
                        print(f"WARNUNG: Konnte Daten in Zeile nicht umwandeln: {zeile}")
                    except IndexError:
                        print(f"WARNUNG: Zeile zu kurz, konnte nicht alle Spalten lesen: {zeile}")
            except StopIteration:
                print("FEHLER: Die CSV-Datei ist leer oder enthält nur eine Kopfzeile.")
            except csv.Error as e:
                print(f"FEHLER beim Lesen der CSV: {e}")
    # (except FileNotFoundError von außen bleibt bestehen)

    Was passiert hier?

    • Wir greifen wie gewohnt auf die Elemente der zeile-Liste zu.
    • Für die Spalten, die Zahlen enthalten sollen, verwenden wir int() (für Ganzzahlen) oder float() (für Kommazahlen, z.B. preis = float(zeile[5])), um den String in eine Zahl umzuwandeln.
    • Wichtig: Diese Umwandlung kann fehlschlagen, wenn in der Zelle unerwartet Text oder ein leerer String steht. Ein Beispiel ist ein Preis mit einem Währungszeichen zusammen wie “42,00 €”. Deshalb packen wir die Umwandlungs- und Verarbeitungslogik für jede Zeile in einen eigenen try…except ValueError-Block. So wird bei einem Fehler nur die betreffende Zeile übersprungen (mit einer Warnung), und das Skript läuft weiter.
    • Nach der Umwandlung können wir die Variablen (hausnummer, plz) wie Zahlen verwenden (z.B. für Vergleiche wie plz > 50000).

    Du möchtest mehr über Datentypen wie Strings, Integers und Floats oder die Grundlagen von Schleifen und Fehlerbehandlung erfahren? Das alles und mehr findest du detailliert erklärt in meinem E-Book „Python Basics: Dein Schlüssel zur Programmierwelt!“

    Der csv.DictReader als komfortable Alternative

    Mit dem csv.reader haben wir die Zeilen als einfache Listen bekommen. Das ist praktisch, um schnell über den Index der Liste auf die einzelnen Elemente zuzugreifen. Natürlich nachdem wir die Kopfzeile übersprungen haben. Das ist schon das erste Problem. Die Verbindung zwischen Kopfzeile und Daten fehlt. Das heißt auch, du musst dir immer merken, welcher Inhalt in welcher Zelle steht. Weisst du jetzt noch aus dem Kopf, in welcher Spalte / Zelle die Hausnummer gefunden werden kann?

    Genau hier kommt der csv.DictReader ins Spiel! Er liest ebenfalls Zeile für Zeile, gibt dir aber statt einer Liste ein Dictionary zurück. Damit musst du die Kopfzeile nicht mehr überspringen und bekommst darüber hinaus noch eine schöne Zuordnung der Daten zu den Spaltennamen. Du kannst also ganz bequem über den Spaltennamen auf die Daten zugreifen.

    Warum DictReader? Die Vorteile

    • Lesbarkeit: Du greifst über die Spaltennamen auf die Daten zu (z.B. zeile[‚Vorname‘] oder besser zeile.get(‚Vorname‘) statt zeile[0]). Das macht deinen Code sofort viel verständlicher und selbsterklärender.
    • Robustheit: Ändert sich die Reihenfolge der Spalten in der CSV-Datei, funktioniert dein Code weiterhin, solange die Spaltennamen gleich bleiben. Beim Index-Zugriff müsstest du alles anpassen.
    • Weniger Fehler: Du musst dir keine Spaltenindizes merken, was die Gefahr von IndexError-Fehlern oder dem Zugriff auf die falsche Spalte reduziert.

    Der csv.DictReader in Aktion

    Die Verwendung ist sehr ähnlich zum csv.reader, nur dass wir jetzt csv.DictReader aufrufen. Die Kopfzeile wird automatisch vom DictReader verwendet und muss nicht mehr manuell mit next() übersprungen werden.

    import csv
    from pathlib import Path
    
    datei_pfad = Path('daten/adressen.csv')
    
    try:
        with open(datei_pfad, 'r', encoding='utf-8', newline='') as csv_datei:
            dict_reader = csv.DictReader(csv_datei, delimiter=',') # Schön den delimiter angeben!!
            print(f"\n--- Lese '{datei_pfad}' als Dictionaries ---")
    
            # jede 'zeile' ist jetzt ein Dictionary
            for zeile_dict in dict_reader:
                # Zugriff über Spaltennamen (Keys des Dictionaries)
                vorname = zeile_dict.get('Vorname')
                nachname = zeile_dict.get('Nachname')
                ort = zeile_dict.get('Ort')
                email = zeile_dict.get('Email')
                print(f"Name: {vorname} {nachname}, Ort: {ort}, E-Mail: {email}")
    except FileNotFoundError:
        print(f"FEHLER: Die Datei '{datei_pfad}' wurde nicht gefunden.")
    except KeyError as e:
        # Den Fehler bekommst du, wenn du den Zugriff über die eckigen Klammern machst und dein Key / Spaltenname nicht existiert. Der Zugriff über .get() behandelt den Fehler schon automatisch
        print(f"FEHLER: Spaltenname {e} in der CSV nicht gefunden. Prüfe die Kopfzeile!")
    except csv.Error as e:
        print(f"FEHLER beim Lesen der CSV: {e}")
    except Exception as e:
        print(f"Ein unerwarteter Fehler ist aufgetreten: {e}")

    Wichtige Punkte:

    • csv.DictReader(csv_datei, delimiter=','): Erstellt den DictReader. Er liest automatisch die erste Zeile und verwendet die Einträge als Schlüssel für die Dictionaries.
    • for zeile_dict in dict_reader: Die Schleife liefert jetzt für jede Zeile ein Dictionary (zeile_dict).
    • zeile_dict['Vorname']: So greifst du einfach über den Spaltennamen direkt auf die Daten zu. Aber Achtung! Existiert der Spaltenname nicht, bekommst du einen KeyError. Deshalb besser zeile_dict.get(‚Vorname‘) verwenden. Gibt es in dem Fall den Spaltennamen nicht, bekommst du einfach gar nichts zurück geliefert. Außerdem kannst du noch Standardwerte setzen, die geliefert werden sollen, falls die Daten nicht existieren. zeile_dict.get(‚Vorname‘, ‚Peter‘) liefert dir entweder den korrekten Inhalt der Spalte, oder “Peter”, falls die Spalte nicht existiert und es zu einem Fehler kommen würde. 
    • Fehlerbehandlung: Statt IndexError fangen wir jetzt KeyError ab, falls du versuchst, auf einen Spaltennamen zuzugreifen, den es in der Kopfzeile nicht gibt.

    Dictionaries sind extrem nützliche Datenstrukturen in Python! Wenn du mehr über ihre Funktionsweise, Methoden und Anwendungsfälle lernen möchtest, findest du ein ausführliches Kapitel dazu in meinem E-Book „Python Basics“

    Robuster Code: Typische Fehler beim CSV-Lesen behandeln

    Kennst du den Spruch “Shit in, shit out”?

    Das ist der Standard Satz, den man hört, wenn es um Datenverarbeitung geht. Leider kann man dem normal nicht folgen. Du bekommst Daten aus verschiedenen Quellen oder Abteilungen. Alle anders bearbeitet. Tippfehler, nicht an die Formatierung gehalten, Spaltennamen mal hinzugefügt, mal weg gelassen.

    Fehlerhafte Formate oder Daten gehören also zum Alltag. Guter Code kümmert sich um so viele Fehler wie möglich, oder zumindest darum, nicht sofort abzustürzen, wenn man irgendwas unerwartetes passiert. Stell dir vor du hast eine Datenverarbeitung die hundertausende Datensätze verarbeitet und irgendwo in der Mitte, nach mehreren Stunden verarbeitung, schlägt etwas fehl, dein Programm stürzt ab und du kannst von vorne beginnen.

    Dafür hast du in Python den try…except-Block, den wir schon in den Beispielen verwendet haben. Im folgenden möchte ich dir die häufigsten Stolpersteine bei der Verarbeitung von CSV-Dateien näher bringen. Hier findest du auch eine schöne Übersicht über die möglichen Fehler, die Python im Standard schon mir bringt.

    Fehler 1: Datei nicht gefunden (FileNotFoundError)

    Wohl der erste Fehler in den du rein läufst. Du gibst einen Pfad an, aber die Datei existiert nicht. Tippfehler im Namen, falscher Ordner, oder einfach nie abgelegt worden. Das ist schnell passiert. 

    Lösung: Am besten fängst du den Fehler direkt nach dem open() ab.

    try:
        with open(datei_pfad, 'r', encoding='utf-8', newline='') as csv_datei:
            # ... Restlicher Code ...
            pass # Platzhalter
    except FileNotFoundError:
        print(f"FEHLER: Die Datei unter dem Pfad '{datei_pfad}' konnte nicht gefunden werden. Bitte Pfad prüfen!")
        # Hier kannst du das Programm beenden, Standardwerte setzen, Mitteilungen ausgeben, etc. Je nachdem was dein Fall erfordert.

    Fehler 2: Probleme beim Parsen (csv.Error)

    Das csv-Modul erwartet ein bestimmtes Format. Wenn etwas Unerwartetes auftritt (z.B. ein plötzlicher Zeilenumbruch innerhalb eines nicht korrekt gequoteten Feldes, ein völlig falsches Dateiformat), wirft der csv.reader oder csv.DictReader oft einen csv.Error. Lösung: Am besten behandelst du den Fehler direkt zu Beginn mit ab. Dann sind auch Probleme beim einlesen mit behandelt.

    try:
        with open(datei_pfad, 'r', encoding='utf-8', newline='') as csv_datei:
            reader = csv.reader(csv_datei, delimiter=',')
            for zeile in reader:
                # Fehler kann auch hier bei spezifischen Zeilen auftreten
                pass # Platzhalter
    except csv.Error as e:
        print(f"FEHLER im CSV-Format: {e}. Prüfe Trennzeichen und Quoting-Regeln.")
    except FileNotFoundError:
        print(f"FEHLER: Datei '{datei_pfad}' nicht gefunden.")

    Fehler 3: Falsche Spaltenanzahl (IndexError bei csv.reader)

    Wenn du mit csv.reader arbeitest und per Index (z.B. zeile[5]) auf Spalten zugreifst, kann es sein, dass deine CSV weniger Spalten hat, als du erwartest. In dem Fall wird dir ein IndexError entgegen geworfen. 

    Lösung: Fange den Fehler am besten direkt an Ort und Stelle ab. Innerhalb der for-Schleife kannst du vorab die Länge der Zeile (also der Liste) prüfen, oder wieder ein try…except einbauen.

    # Innerhalb der for-Schleife:
    try:
        email = zeile[6] # Zugriff auf die 7. Spalte
    except IndexError:
        print(f"WARNUNG: Zeile hat zu wenige Spalten: {zeile}")

    Fehler 4: Spaltenname nicht gefunden (KeyError bei csv.DictReader)

    Wenn du mit csv.DictReader arbeitest und per Spaltenname (z.B. zeile_dict[‚Email‘]) zugreifst, aber dieser Name in der Kopfzeile deiner CSV nicht existiert, bekommst du einen KeyError. 

    Lösung: Entweder den KeyError innerhalb der for-Schleife abfangen oder (besser!) die .get()-Methode verwenden.

    # Innerhalb der for-Schleife:
    try:
        # Zugriff über Klammern auf eigenes Risiko
        # email = zeile_dict['Email']
        email = zeile_dict.get('Email')  # Gibt None zurück, wenn 'Email' fehlt, erlaubt Standard-Werte
        if email is None:
            print(f"WARNUNG: Spalte 'Email' in Zeile nicht gefunden: {zeile_dict}")
        else:
            pass
    except KeyError as e: # Falls doch Klammerzugriff verwendet wird
         print(f"FEHLER: Spaltenname {e} nicht gefunden.")

    Fehler 5: Typumwandlung schlägt fehl (ValueError)

    Wenn du versuchst, einen String, der keine gültige Zahl ist (z.B. „N/A“, „12.34 Euro“, oder ein leerer String), mit int() oder float() umzuwandeln, bekommst du einen ValueError. 

    Lösung: Fange den ValueError innerhalb der for-Schleife für jede Zeile ab, in der du Typumwandlungen vornimmst.

    # Innerhalb der for-Schleife:
    try:
        plz_text = zeile_dict.get('PLZ', '') # Hole PLZ oder leeren String
        if plz_text: # prüfe, ob du Inhalt hast
            plz = int(plz_text)
        else:
            # Hier kommt die Behandlung, falls die plz leer ist
            pass
    except ValueError:
        print(f"WARNUNG: Konnte PLZ '{plz_text}' nicht in Zahl umwandeln: {zeile_dict}")

    Fehler 6: Falsches Encoding (UnicodeDecodeError)

    Wenn du die falsche Zeichenkodierung (z.B. encoding=’ascii‘ statt encoding=’utf-8′) beim open() angibst und die Datei Umlaute oder Sonderzeichen enthält, wird das schnell mit einem UnicodeDecodeError quittiert. 

    Lösung: Stelle sicher, dass du die korrekte Kodierung verwendest (meistens ‚utf-8‘). Falls du die Kodierung nicht kennst, musst du sie eventuell durch rumprobieren herausfinden. Weitere, häufige Kodierungen sind ‚latin-1‘ oder auch ‚cp1252′. Als letzter Not-Hammer kannst auch noch errors=’ignore‘ oder errors=’replace‘ an open() setzen. Dabei riskierst du aber Datenverlust!

    try:
        with open(datei_pfad, 'r', encoding='utf-8', newline='') as csv_datei:
            pass
    except UnicodeDecodeError:
        print(f"WARNUNG: Konnte Datei '{datei_pfad}' nicht mit UTF-8 lesen. Versuche latin-1...")
        try:
            # Fallback-Versuch mit anderer Kodierung
            with open(datei_pfad, 'r', encoding='latin-1', newline='') as csv_datei:
                pass
        except Exception as e:
            print(f"FEHLER: Konnte Datei auch mit latin-1 nicht lesen: {e}")
    except FileNotFoundError:
         print(f"FEHLER: Datei '{datei_pfad}' nicht gefunden.")

    Mehr über Fehler und Exceptions lernen?

    Robuster Code ist entscheidend! Die Grundlagen der Fehlerbehandlung mit try…except, spezifische Exception-Typen und wie du sie effektiv nutzt, erkläre ich ausführlich im Kapitel „Errors und Exceptions“ meines E-Books „Python Basics“

    Der nächste Schritt: Große Dateien & Datenanalyse mit Pandas

    Das csv-Modul ist perfekt für grundlegende Lese- und Schreibaufgaben und hat den großen Vorteil, dass es immer verfügbar ist. Wenn du aber komplexere Anforerdungen, weitreichende Datenanalyse oder wirklich große Dateien (mehrere hundert MB oder gar GB) vor dir hast, stößt das Standardmodul an seine Grenzen.

    Pandas ist hier das Tool der Wahl! Es ist die De-facto-Standardbibliothek für Datenanalyse in Python.

    Wann ist Pandas die bessere Wahl?

    • Große CSV-Dateien: Pandas ist optimiert, um auch große Datenmengen effizient einzulesen. Dafür arbeitet es die Daten häppchenweise durch, hat eigene Datentypen, die intern verwendet werden, und einiges mehr. Du siehst davon allerdings nichts. Für dich bleibt die Arbeit einfach.
    • Komfortable Datenstrukturen: Pandas liest Daten in sog. DataFrames ein – das sind leistungsstarke, tabellenähnliche Strukturen mit Spaltennamen, Zeilenindizes und vielen eingebauten Funktionen.
    • Daten bereinigen und transformieren: Fehlende Werte behandeln, Datentypen intelligent umwandeln, Spalten hinzufügen/entfernen, Daten filtern und sortieren – all das geht mit Pandas viel einfacher und eleganter.
    • Analysieren und aggregieren: Gruppieren von Daten, Berechnen von Statistiken (Mittelwert, Summe etc.), Zusammenführen verschiedener Tabellen (ähnlich wie JOINs in SQL) sind Kernfunktionen von Pandas.
    • Zeit sparen: Für viele gängige Datenmanipulationsaufgaben brauchst du mit Pandas weniger Code als mit reinem Python und dem csv-Modul.

    Kleiner Einblick: pandas.read_csv

    Pandas zu installieren (pip install pandas) und zu verwenden ist überraschend einfach. Das Einlesen einer CSV-Datei reduziert sich oft auf eine einzige Zeile:

    import pandas as pd # Konvention: Pandas als 'pd' importieren
    from pathlib import Path
    datei_pfad = Path('daten/adressen.csv')
    try:
        # CSV direkt in einen Pandas DataFrame einlesen
        # Pandas versucht, Trennzeichen und Header oft automatisch zu erkennen!
        # Ggf. muss man delimiter=';' oder andere Parameter angeben.
        daten_df = pd.read_csv(datei_pfad)
        # Zeige die ersten 5 Zeilen des DataFrames an
        print("\n--- Daten gelesen mit Pandas (erste 5 Zeilen): ---")
        print(daten_df.head())
        # Beispiel: Zugriff auf die Spalte 'Ort'
        # print("\nOrte:")
        # print(daten_df['Ort'])
    except FileNotFoundError:
        print(f"FEHLER: Die Datei '{datei_pfad}' wurde nicht gefunden.")
    except pd.errors.EmptyDataError: # Spezifischer Pandas-Fehler für leere Dateien
        print(f"FEHLER: Die Datei '{datei_pfad}' ist leer.")
    except Exception as e:
        print(f"FEHLER beim Lesen mit Pandas: {e}")

    Das ist natürlich nur die Spitze des Eisbergs! Pandas bietet eine riesige Funktionsvielfalt.

    Wenn du aus der Excel-Welt kommst und lernen möchtest, wie du deine Datenanalyse und -automatisierung mit der Power von Pandas auf das nächste Level hebst, dann ist ein Einstieg mit meinem Videokurs „Von Excel zu Python: Datenanalyse leicht gemacht!“ genau das Richtige für dich!

    Zusammenfassung & Ausblick

    Das war’s schon! Schade, oder? 😉 Du hast jetzt einen umfassenden Überblick bekommen, wie du CSV-Dateien zuverlässig mit Pythons eingebautem csv-Modul lesen kannst.

    Die wichtigsten Punkte im Überblick:

    • Datei öffnen: Immer mit with open(…, encoding=’utf-8′, newline=“) für sauberen Code und korrekte Behandlung von Umlauten und Zeilenenden.
    • Lesen als Listen: csv.reader() liefert dir jede Zeile als Liste. Zugriff über den Index (z.B. zeile[0]).
    • Lesen als Dictionaries: csv.DictReader() ist oft komfortabler und robuster, da die Kopfzeile als Schlüssel verwendet wird. Zugriff erfolgt über den Spaltennamen (z.B. zeile_dict.get(‚Spaltenname‘)).
    • Flexibilität: Mit Parametern wie delimiter und quotechar kannst du dich an verschiedene CSV-Formate anpassen.
    • Robustheit: Denke an die Fehlerbehandlung! Fange typische Fehler wie FileNotFoundError, csv.Error, ValueError oder KeyError/IndexError mit try…except ab.
    • Der nächste Schritt (Pandas): Für große Dateien und komplexe Datenanalysen ist die Pandas-Bibliothek (pd.read_csv()) oft die effizientere Wahl.

    Wie geht es weiter?

    Nachdem du weißt, wie du Daten einliest, möchtest du sie vielleicht auch wieder in eine CSV-Datei schreiben? Dann hop hop, gleich weiter zum nächsten Artikel!

    Picture of Ingo Janßen

    Ingo Janßen

    Lerne nicht einfach programmieren. Löse Probleme und automatisiere Aufgaben!

    Das könnte dich auch interessieren

    Nach oben scrollen