CSV Dateien lesen mit Python

CSV Dateien begegnen einem überall.
Ob direkt als CSV oder als Excel Format, das auch nur eine hübsche Darstellung für CSV ist, ist dabei egal.
So oder so müssen wir fast täglich mit dem Format umgehen.

Da wäre es doch praktisch die Daten auch in dem Format schnell einlesen und auch schreiben zu können, oder?

Genau darum soll es in diesem Beitrag gehen.

Ein kleiner Hinweis noch:
Ich werde in diesem Artikel ausschließlich auf CSV und den Umgang damit eingehen.
Hier findest du einen Artikel der allgemein den Umgang mit Dateien erklärt.

Du weißt nicht, was du mit den Dateien machen sollst?
Hier findest du Hilfe.

Hier findest du auch ein Video zum Artikel:

Wie kann ich CSV Daten einlesen?

Zum Einlesen von CSV Daten musst du zuerst die Datei öffnen. Anschließend kannst du mit dem Modul ‚csv‘ einen ‚reader‘ erzeugen und die Datei Zeile für Zeile einlesen. Dabei wird jede Zeile als Liste dargestellt, wobei die Einträge in der Liste jeweils eine Zelle repräsentieren.

Aber alles nochmal langsam und Schritt für Schritt:

Schritt 1: Datei öffnen

with open('/content/drive/MyDrive/posts/dateien/adressen/adressen.csv', 'r') as csv_datei:

Mit with open() öffnest du erstmal die Datei.
Dabei bekommt open() zuerst den Pfad übergeben, gefolgt von der Operation für die die Datei geöffnet werden soll. In dem Fall r für read / lesen.

Am Ende hängst du noch einen Variablennamen mit as an.
Der ist nötig, damit du den Datei-Handle später auch ansprechen und eben Daten einlesen kannst.
Es ist ein Variablenname. Also für dich frei wählbar. Nimm nur irgendwas sprechendes, damit du später auch noch weißt, was für eine Datei es ist, mit der du da hantierst.

Schritt 2: Trennzeichen definieren

import csv
with open('/content/drive/MyDrive/posts/dateien/adressen/adressen.csv', 'r') as csv_datei:
    reader = csv.reader(csv_datei, delimiter=',')

Jetzt kommt das csv Modul zum Einsatz. Also erstmal importieren und anschließend kannst du damit einen reader erzeugen.
Der reader ist ein Objekt, das weiß wie die Datei zu lesen ist und mit dessen Hilfe du dann die verschiedenen Leseoperationen ausführen kannst.

Beim erzeugen gibst du erstmal deinen Datei-Handle an den reader. Immerhin muss er ja wissen, woher er die Daten nehmen soll.

Außerdem handelt es sich um einen CSV reader.
CSV steht zwar für Comma separated value, das heißt aber noch lange nicht, dass CSVs auch immer mit einem Komma separiert werden.
Es können auch Semikolon (;) oder Tabs oder sonstige Zeichen für die Trennung von Zellen genommen worden sein.

Um genau das Problem anzugehen hat der reader noch den Parameter delimiter.
Mit dem delimiter kannst du angeben wie genau deine CSV Datei die Zellen getrennt hat. Damit weiß der reader dann was eine Zelle ist und wie die Daten zu behandeln sind.

Schritt 3: Daten einlesen

import csv
with open('/content/drive/MyDrive/posts/dateien/adressen/adressen.csv', 'r') as csv_datei:
    reader = csv.reader(csv_datei, delimiter=',')

    for zeile in reader:
        print(zeile)

Nachdem der reader jetzt weiß, wie er die Zeilen und Zellen einzulesen hat, erstellt er daraus einfach eine lange Liste mit einzelnen Listen für jede Zeile.
Und die Einträge in jeder Zeile sind dann die Zellen.

Jede Zeile ist als Liste dargestellt. Und so kannst du natürlich auch auf die einzelnen Elemente der Liste zugreifen und dir einzelne Werte herausziehen, die du gerade brauchst.
Zum Beispiel nur Vorname und Nachname:

import csv
with open('/content/drive/MyDrive/posts/dateien/adressen/adressen.csv', 'r', encoding='utf-8') as csv_datei:
    reader = csv.reader(csv_datei, delimiter=',')

    for zeile in reader:
        print(f'Vorname: {zeile[0]} - Nachname: {zeile[1]}')

Anmerkung:
Solltest du Probleme mit Umlauten und Sonderzeichen bei der Ausgabe feststellen, kannst du dem open() auch noch einen weiteren Parameter encoding mit übergeben.
Mit encoding kannst du angeben, welchen Zeichensatz deine Daten beinhalten und wie Python die Daten behandeln sollte.
In unserem Raum ist es meist ‚UTF-8‘. Damit sind dann auch Sonderzeichen und Umlaute beinhaltet.

Schritt 4: Kopfzeile abtrennen

Die Kopfzeile beschreibt nur die einzelnen Spalten in den Daten. Wenn du die Daten also sortieren und in ein anderes Format bringen möchtest, musst die Kopfzeile erstmal loswerden.
Da die Kopfzeile einfach die erste Zeile in der Datei ist, ist es auch einfach die loszuwerden, bzw. herauszulösen. Dafür muss einfach nur eine Zeile weiter gesprungen werden.

Bei einem iterierbaren Objekt wie dem reader ist es möglich ein Element weiterzuspringen. Dafür nutzt du einfach das BuiltIn next().
Durch next() bekommst du immer das nächste Element geliefert und das Objekt – also der reader in dem Fall – merkt sich, dass dieses Element schon geliefert wurde.

Die for-Schleife nutzt intern auch ein next() um dir fortlaufend das nächste Element liefern zu können.

Also einmal den Kopf abschlagen 😉

import csv

with open('/content/drive/MyDrive/posts/dateien/adressen/adressen.csv', 'r', encoding='utf-8') as csv_datei:
    reader = csv.reader(csv_datei, delimiter=',')

    kopfzeile = next(reader)

    for zeile in reader:
        print(f'Vorname: {zeile[0]} - Nachname: {zeile[1]}')

Schritt 5: Daten zuordnen

Als Nächstes möchte ich die Daten einmal zuordnen. Also einen Bezug herstellen und sehen, was der Wert eigentlich ist.
Zuordnungen lassen sich einfach über ein Dictionary lösen, da ein Dictionary ja immer ein Schlüssel-Werte-Paar darstellt.
Also eine Zuordnung.

Dafür legst du zuerst ein Dictionary kontakte an. In dem soll der Schlüssel dann immer die Beschreibung der Daten sein – also zum Beispiel Vorname – und der Wert eben der jeweils zugehörige Wert – also zum Beispiel Ingo.

Das sieht dann am Ende in etwa so aus:

kontakte = [
    {
        'Vorname': 'Ingo',
        'Nachname': 'Janssen'
    }
]

Jetzt hast du natürlich nicht nur einen Datensatz und auch mehr als 2 Spalten. Lass also Python die Arbeit machen!

Die Kopfzeile ist schon losgelöst. Du kannst also immer den ersten Eintrag aus der kopfzeile mit dem ersten Eintrag aus der zeile in Verbindung setzen. Dann den zweiten Eintrag und so weiter.

In dem Beispiel hat die Kopfzeile 7 Einträge. Das lässt sich noch einfach per Hand zuordnen:

import csv

kontakte = []

with open('/content/drive/MyDrive/posts/dateien/adressen/adressen.csv', 'r', encoding='utf-8') as csv_datei:
    reader = csv.reader(csv_datei, delimiter=',')

    kopfzeile = next(reader)

    for zeile in reader:
        eintrag = {
            kopfzeile[0]: zeile[0],
            kopfzeile[1]: zeile[1],
            kopfzeile[2]: zeile[2],
            kopfzeile[3]: zeile[3],
            kopfzeile[4]: zeile[4],
            kopfzeile[5]: zeile[5],
            kopfzeile[6]: zeile[6]
        }
        kontakte.append(eintrag)

print(kontakte)

Schritt 6: Zuordnung automatisieren

Wie gesagt hat die Kopfzeile hier nur 7 Einträge und lässt sich damit noch wunderbar manuell zuordnen. Oft gibt es aber auch CSV Dateien mit 20, 30, 50 und mehr Spalten!
Die willst du sicher nicht mehr manuell zuordnen, oder? 😉

Deshalb schreiben wir jetzt den Code einfach ein klein wenig um, damit es egal wird wie viele Spalten am Ende in der CSV vorhanden sind. Die Zuordnung wird einfach automatisch gemacht.

Wie? Einfach!
Die Kopfzeile ist auch nur eine Liste mit den Spaltenbezeichnern.
Also kannst du beim Durchlaufen der einzelnen Zeilen einfach zusätzlich noch die Spalten durchlaufen.
Für jede Zeile durchläufst du also einmal alle Spalten. Damit bekommst du schonmal den Spaltennamen, den du ja als Schlüssel in deinem Dictionary haben möchtest.

Zusätzlich kannst du noch das BuiltIn enumerate() verwenden.
Wenn du beim Durchlaufen eines iterierbaren Objektes – also zum Beispiel einer Liste – eben diese Liste an enumerate(liste) übergibst, dann bekommst du mit jedem Durchlauf zwei Werte: Den nächsten Wert aus der Liste die du durchläufst und zusätzlich noch den Index des Wertes.

Hier ein kurzes Beispiel zur Veranschaulichung:

liste = ['eintrag 1', 'eintrag 2', 'eintrag 3']
for index, eintrag in enumerate(liste):
    print(f'Index: {index} - Eintrag: {eintrag}')

Wie du siehst: zu jedem Eintrag ein Index.
Und was kannst du mit einem Index machen?

Auf Listen zugreifen!
Wenn du also für jede Zeile einmal die gesamte Kopfzeile durchläufst und dabei einen Index bekommst, weißt du, dass der Spaltenbezeichner Vorname den Index 0 hat. Und genau an dem Index steht auch der wirkliche Vorname in deinen Daten. Also in zeile[0]

Das Wissen jetzt zusammengeführt und du kannst deine Einträge automatisch erstellen lassen:

import csv

kontakte = []

with open('/content/drive/MyDrive/posts/dateien/adressen/adressen.csv', 'r', encoding='utf-8') as csv_datei:
    reader = csv.reader(csv_datei, delimiter=',')

    kopfzeile = next(reader)

    for zeile in reader:
        eintrag = {}
        for idx, spalte in enumerate(kopfzeile):
            eintrag[spalte] = zeile[idx]
        kontakte.append(eintrag)

print(kontakte)

Das gibt eine lange Liste mit lauter Dictionaries als einzelne Kontakteinträge.
Schön, aber übersichtlich ist was anderes. Und durchsuchbar ist es auch nicht.
Also lass doch einfach mal die kontakte auch noch in ein Dictionary umwandeln.
Um es einfach zu halten, nehmen wir hier den Vor- und Nachnamen als Schlüssel für die Kontakte.
Das gibt dir den Vorteil, dass du später einfach mit kontakte[name] auf deine Daten zugreifen kannst und sofort den gesamten Datensatz dazu findest. Wie es halt früher in den kleinen Papierkontaktbüchlein auch war.

Aber Achtung:
Vor- und Nachname ist natürlich nicht zwingend eindeutig!
Wir benutzten das hier zwar, um den Code vorerst einfach zu halten, aber wenn du das in der Praxis verwenden möchtest, solltest du dir einen besseren, eindeutigeren Schlüssel für deine Kontakte überlegen.
Andernfalls werden bei Duplikaten die Einträge natürlich einfach überschrieben und dir gehen Daten verloren!

import csv

kontakte = {}

with open('/content/drive/MyDrive/posts/dateien/adressen/adressen.csv', 'r', encoding='utf-8') as csv_datei:
    reader = csv.reader(csv_datei, delimiter=',')

    kopfzeile = next(reader)

    for zeile in reader:
        eintrag = {}
        for idx, spalte in enumerate(kopfzeile):
            eintrag[spalte] = zeile[idx]
        name = f'{zeile[0]} {zeile[1]}'
        kontakte[name] = eintrag

print(kontakte)

Schritt 7: Darstellung optimieren

Perfekt!
Schon sind die Daten schön zugeordnet. Nur leserlich ist es noch nicht so in einer endlos langen Zeile.
Das lässt sich aber natürlich auch einfach ändern.
Dafür kannst du das json Modul verwenden.

Mit dem json Modul kannst du Python Datenstrukturen einfach einen JSON Text umwandeln und auch gleich formatieren lassen.
Wenn du mehr zu dem Modul lesen möchtest, dann sieh dir meinen Artikel dazu hier an.

import csv
import json

kontakte = {}

with open('/content/drive/MyDrive/posts/dateien/adressen/adressen.csv', 'r', encoding='utf-8') as csv_datei:
    reader = csv.reader(csv_datei, delimiter=',')

    kopfzeile = next(reader)

    for zeile in reader:
        eintrag = {}
        for idx, spalte in enumerate(kopfzeile):
            eintrag[spalte] = zeile[idx]
        name = f'{zeile[0]} {zeile[1]}'
        kontakte[name] = eintrag

print(kontakte)
json_text = json.dumps(kontakte)
print(json_text)

Also einmal oben json importieren und dann unten mit json.dumps(kontakte) das kontakte Dictionary in JSON umwandeln und ausgeben.

Aber großartig anders sieht das jetzt nicht aus…
Dafür kannst du der dumps() Funktion noch den Parameter indent mitgeben.
Mit indent gibst du an, wie weit der jeweils nächste Eintrag eingerückt werden soll. Dir wird dein JSON Text also formatiert und das gleich mit der Anzahl an Leerzeichen, die du gerne hättest.

Ich persönlich nutze eigentlich immer die 4 als Einrückung. Das ist auch die Einrückung in Python und macht es so angenehm leserlich:

import csv
import json

kontakte = {}

with open('/content/drive/MyDrive/posts/dateien/adressen/adressen.csv', 'r', encoding='utf-8') as csv_datei:
    reader = csv.reader(csv_datei, delimiter=',')

    kopfzeile = next(reader)

    for zeile in reader:
        eintrag = {}
        for idx, spalte in enumerate(kopfzeile):
            eintrag[spalte] = zeile[idx]
        name = f'{zeile[0]} {zeile[1]}'
        kontakte[name] = eintrag

print(kontakte)
json_text = json.dumps(kontakte, indent=4)
print(json_text)

Das sieht doch schon viel besser aus!
Alle Kontakte schön untereinander, alle Einträge schön untereinander, so lässt sich das lesen!

Aber Moment… Sieh dir mal den zweiten Eintrag – Dietmar Köhler – etwas genauer an.
Sein Name sieht irgendwie komisch aus, oder?
Das liegt daran, dass das JSON Format für das Web gedacht ist.
Und das Web kann nicht sonderlich gut mit Umlauten, Sonderzeichen oder UTF-8 Text umgehen.
Deswegen versucht JSON bei der Umwandlung derartige Sonderzeichen direkt Web-tauglich in sogenanntes ASCII umzuwandeln.

Ein Browser könnte das dann wieder lesen und korrekt zurückwandeln, sodass die Darstellung wieder passt.
Hier brauchst du das natürlich nicht und es stört nur.

Zum Glück bietet das json Modul die Möglichkeit diese Funktion auszuschalten. Dafür musst du lediglich einen weiteren Parameter übergeben.
Mit ensure_ascii kannst du einstellen, ob das json Modul ein ASCII konformes Ergebnis sicherstellen soll (Standard) oder eben nicht.
Also einfach ein ensure_ascii=False mit übergeben und schon sind die Umlaute wieder korrekt:

import csv
import json

kontakte = {}

with open('/content/drive/MyDrive/posts/dateien/adressen/adressen.csv', 'r', encoding='utf-8') as csv_datei:
    reader = csv.reader(csv_datei, delimiter=',')

    kopfzeile = next(reader)

    for zeile in reader:
        eintrag = {}
        for idx, spalte in enumerate(kopfzeile):
            eintrag[spalte] = zeile[idx]
        name = f'{zeile[0]} {zeile[1]}'
        kontakte[name] = eintrag

print(kontakte)
json_text = json.dumps(kontakte, indent=4, ensure_ascii=False)
print(json_text)

Zusammenfassung

  • Einlesen mit with open()
  • Reader mit csv.reader() erzeugen
  • Reader konfigurieren (Datei-Handle und Delimiter übergeben)
  • Kopfzeile von Daten lösen
  • Daten Zeile für Zeile in ein Dictionary einlesen
  • Optional: Daten mit json schön darstellen

Das war’s!
So einfach kannst du beliebige CSV Daten in deine Programme einlesen. Und dabei hast du sie dann sogar direkt in nativen Python Datentypen zur Verfügung!

Im nächsten Artikel zeige ich dir, wie du die eingelesenen Daten wieder in eine CSV Struktur bekommst und in eine Datei schreiben kannst.

Also bleib unbedingt dran!

Scroll to Top