CSV ist ein sehr beliebtes Format.
Fast jedes System ist irgendwie in der Lage “Flat-Files” zu erzeugen, in denen sich Komma-separierte Daten befinden.
Aus verschiedenen Gründen kann es aber passieren, dass die Daten nicht in einem Rutsch vollständig exportiert werden.
Das können Begrenzungen der Dateigrößen sein, Anzahl der Zeilen oder vielleicht liegen einfach zeitliche Abstände dazwischen, wie zum Beispiel bei einem monatlichen Export der Kontobewegungen.
Um einen vollständigen Überblick zu bekommen und die Dateien auswerten zu können ist es natürlich hilfreich, die Daten erstmal wieder zusammenzuführen und in eine große Datei zu schreiben.
Im Grundsatz folgt es immer denselben Schritten:
Alle Dateien mit os.listdir() auflisten und mit einer Bedingung (if) filtern.
Die gefilterten Dateien in einer for-Schleife mit with open() öffnen undmit dem csv Modul einlesen.
Abschließend mit with open() eine neue Datei erzeugen und die Daten mit dem csv Modul in die neue Datei schreiben.
Wie du genau das mit nur ein paar Zeilen Python Code erledigen kannst, will ich dir in diesem Artikel zeigen.
Dabei fangen wir erstmal mit einfachem einlesen und schreiben an, gehen dann über zu mehreren Dateien und schlussendlich zu beliebig vielen Dateien aus einem Verzeichnis.
Dateien zum Beitrag:
Du weißt nicht, was du mit den Dateien machen sollst? Hier findest du Hilfe.
Wie kann ich CSV Dateien einlesen?
Mit with open() kannst du eine Datei öffnen.
Der reader aus dem csv Modul hilft dir dann beim Einlesen der Daten.
import csv
with open('dateien/mitarbeiter_1.csv', 'r') as mitarbeiter_daten:
reader = csv.reader(mitarbeiter_daten, delimiter=',')
for row in reader:
print(row)
Du willst mit CSV Daten arbeiten.
Da CSV Daten so weit verbreitet sind, bringt Python natürlich auch gleich ein paar Hilfen für den Umgang mit solchen Daten mit.
Das lässt du dir natürlich nicht entgehen und importierst direkt mal das CSV Modul 😉
Mit with open() kannst du Dateien öffnen.
Das with kümmert sich dabei darum, die Dateien nach der Verwendung wieder sauber zu schließen, während das open() die Datei öffnet.
Das with öffnet immer einen Block.
Das heißt alles, was passieren soll während die Datei geöffnet ist, wird eingerückt unter der with Zeile geschrieben.
Sobald die Einrückung beendet wird, wird auch die Datei automatisch geschlossen.
Dem open() musst du dann lediglich einen Pfad übergeben wo die Datei zu finden ist, die geöffnet werden soll. Dazu noch ein Parameter, der angibt, wie die Datei geöffnet werden soll.
Also ‘r’ für read (lesen) oder ‘w’ für write (schreiben).
Am Ende folgt noch ein Alias.
Das ist einfach ein Bezeichner, ein Name, den du frei wählen kannst. Unter dem Namen kannst du die Datei dann später im Code ansprechen und verwenden.
In dem Block willst du die Datei einlesen.
Und genau dafür liefert dir das CSV Modul eine Hilft mit dem reader.
Der Funktion reader() übergibst du einmal deinen Verweis auf die Datei, also deinen Alias, und sagst ihm dann noch durch welches Trennzeichen die CSV Spalten voneinander getrennt sind.
Spalten werden manchmal durch ein Komma (,), Semikolon(;), Tab ( ) oder sonstige Zeichen getrennt.
Damit du mit allen diesen verschiedenen Variationen arbeiten kannst, kannst du im delimiter einfach angeben, welches Trennzeichen hier verwendet werden soll.
Damit weiß der Reader, wie er die Daten interpretieren muss und kann die Spalten sauber voneinander trennen.
Den Reader kannst du dir dann vorstellen wie ein Zeiger auf die jeweilige Zeile in der Datei.
Er selbst hat keine Daten, merkt sich aber, wo er als Nächstes lesen muss.
Das heißt mit jedem Schleifendurchlauf liest er die Zeile ein, auf die er gerade zeigt und springt dann mit seinem Zeiger eine Zeile weiter, um für den nächsten Aufruf bereit zu sein.
Du hältst damit also nie die gesamte Datei im Speicher und hast die Möglichkeit theoretisch beliebig große Dateien einzulesen und Zeile für Zeile zu bearbeiten.
In dem Fall läuft einfach eine for-Schleife über den Reader und gibt mit print() Zeile für Zeile den Inhalt aus.
Wenn du dir die Ausgabe ansiehst, wirst du feststellen, dass jede Zeile in eine Liste umgewandelt wurde.
Jede Zeile ist also eine Liste und jede Zelle in der Zeile ist ein Eintrag in eben dieser Liste.
Aber eine lange Liste mit allen Daten zu haben, ohne irgendwie irgendeine Sortierung hilft auch nicht viel weiter. Dann kannst du auch einfach die Datei aufmachen. Das hat denselben Effekt.
Deshalb wäre es doch hilfreich, erstmal die Kopfzeile, also die Spaltenbezeichner von den restlichen Daten zu trennen.
Also weg mit der for-Schleife.
import csv
with open('dateien/mitarbeiter_1.csv', 'r') as mitarbeiter_daten:
reader = csv.reader(mitarbeiter_daten, delimiter=',')
header = next(reader)
daten = [row for row in reader]
Wie vorhin erklärt, zeigt der Reader immer auf die Zeile, die er als Nächstes auslesen soll.
Erst, wenn du die Zeile ausliest, bekommst du die Daten und der Reader springt auf die nächste Zeile.
Um den Header, also die Kopfzeile mit den Spaltennamen zu bekommen, musst du einmal eine Zeile einlesen.
Das Python BuiltIn next() macht genau das.
Es ruft next() an einem iterierbaren Objekt – also zum Beispiel einer Liste – auf und liefert einfach das nächste Element in der Reihe.
In dem Fall ist das die Kopfzeile.
Der Reader gibt also die Kopfzeile zurück und springt dann eins weiter. Damit zeigt er auf den ersten Datensatz in der Datei.
Die Kopfzeile speicherst du dir in der Variablen header, um sie später weiter verwenden zu können.
Um jetzt auch alle Daten auszulesen und im Speicher zu halten kannst du eine Variable daten anlegen und mit einer for-Schleife die Daten einlesen.
Da es eine einfache for-Schleife ist – und um es kürzer zu machen – habe ich in dem Fall einfach eine List-Comprehension benutzt. Das ist auch nur eine for-Schleife, aber eben als Einzeiler geschrieben.
Wie kann ich CSV Dateien schreiben?
Mit with open() und dem Modus ‘w’ (write / schreiben) kannst du eine neue Datei erzeugen.
Der writer aus dem CSV Modul schreibt dann mit writerow, bzw. writerows eine oder mehrere Zeilen in die Datei.
Sehr schön! Du hast die Daten jetzt also in Variablen eingelesen und das getrennt nach Kopfzeile und Daten.
Um es einfach zu halten, schreibst du die Daten jetzt erst einmal so wie sie sind wieder in eine Datei. Wenn das klappt, ist es kein Problem mehr beliebig viele Dateien in einer Datei zusammenzufassen.
Mit with open() hast du vorhin die Datei im Modus ‘r’ (read / lesen) geöffnet, um sie einzulesen. Willst du in eine Datei schreiben, bzw. eine neue Datei anlegen, in die reingeschrieben wird, dann kannst du das mit dem Modus ‘w’ (wirte / schreiben) erledigen.
import csv
header = []
daten = []
with open('dateien/mitarbeiter_1.csv', 'r') as mitarbeiter_daten:
reader = csv.reader(mitarbeiter_daten, delimiter=',')
header = next(reader)
daten = [row for row in reader]
with open('ergebnis.csv', 'w') as ergebnis_daten:
writer = csv.writer(ergebnis_daten, delimiter=',')
writer.writerow(header)
writer.writerows(daten)
Zuerst musst du die Variablen header und daten global – also über deinem anderen Code – definieren.
Bisher stehen sie eingerückt unter dem with open() und sind damit in einem Block. Variablen, die in einem Block erstellt werden, sind auch nur in diesem Block gültig. Durch das Schreiben vor dem anderen Code erstellst du die Variablen schon außerhalb und benutzt sie nur noch in deinem Block und belegst sie mit Daten.
Jetzt erstellst du einen neuen with open() Block mit dem Modus ‘w’ (write / schreiben). Damit erzeugst du eine neue Datei ‘ergebnis.csv‘ in die geschrieben werden kann.
Mit dem CSV Modul lässt sich auch ein writer erstellen. Das funktioniert genauso wie vorher schon der reader. Einfach den Datei-Alias und einen delimiter – ein Trennzeichen für die einzelnen Spalten – übergeben.
Über writerow() kannst du eine einzelne Zeile schreiben.
Mit writerows(), also plural, kannst du eine ganze Reihe von Zeilen auf einmal schreiben.
Weil du die Variablen header und daten außerhalb des with open() Blocks definiert hast, kannst du sie jetzt wiederverwenden und deine eingelesenen Daten in die Datei schreiben.
Dafür übergibst du zuerst den header als eine Zeile mit writerow(header) und anschließend alle deine Daten mit writerows(daten) auf einmal. Führst du den Code jetzt aus, wird eine neue Datei erzeugt und du hast deine Daten mit Kopfzeile da drin stehen.
Das Ganze lässt sich jetzt auch noch etwas abkürzen. Statt zwei unabhängige Blöcke zu erzeugen und erst umständlich die Daten einzulesen, kannst du alles gleich in einem Aufwasch erledigen.
Dafür kannst du in deinem with open() Block in dem du die Daten einliest direkt den with open() Block erstellen, der die Daten schreibt. Damit überspringst du das ein- und auslesen der Variablen und benutzt direkt den reader, um die Daten von einer Datei in die Andere zu schreiben.
import csv
with open('dateien/mitarbeiter_1.csv', 'r') as mitarbeiter_daten:
reader = csv.reader(mitarbeiter_daten, delimiter=',')
with open('ergebnis.csv', 'w') as ergebnis_daten:
writer = csv.writer(ergebnis_daten, delimiter=',')
writer.writerow(next(reader))
writer.writerows([row for row in reader])
Wie kann ich mehrere CSV Dateien zusammenführen?
Lies alle Dateien mit with open() ein und sammel die Daten in einer Variablen. Nachdem alles eingelesen ist, kannst du in einem weiteren with open() BLock alle Daten auf einen Schlag in eine neue Datei schreiben.
Von einer Datei in eine andere zu kopieren, ist aber nicht wirklich dein Ziel. Dafür gibt es ja einfachere Möglichkeiten.
Sinnvoll wird es erst, wenn du mehrere Dateien zusammenführen möchtest. Und genau das sehen wir uns jetzt im nächsten Schritt an.
Also erstmal einen Schritt zurück:
Die Variablen sind wieder global – also oberhalb von deinem Code – definiert.
Dann kommt ein Block zum Einlesen der Daten in header und daten getrennt.
Am Ende findest du wieder den Block, der die Daten in deine ergebnis.csv schreibt.
Soweit alles bekannt.
Um jetzt eine weitere Datei einzulesen brauchst du einfach nur einen weiteren with open() Block für die neue Datei, die du einlesen möchtest. Allerdings hast du den header ja bereits eingelesen. Den kannst du also ignorieren und mit next(reader) einfach auf die nächste Zeile weiter springen, ohne die eingelesenen Daten irgendwie in einer Variablen zu speichern.
Du brauchst sie ja nicht.
Das Einzige, was du jetzt noch ändern musst, ist die Arbeit mit deiner Variablen daten.
Da du bereits Daten eingelesen und in der Variablen gespeichert hast, willst du die ja nicht überschreiben. Eine einfache Zuweisung mit dem ‘=’ würde aber genau das machen. Deine Daten würden überschrieben und alles, was du aus der ersten Datei eingelesen hast, wäre verloren.
Die Variable daten ist eine Liste mit Zeilen. Durch die List-Comprehension wird eine weitere Liste mit Zeilen erzeugt. Du hast also am Ende zwei Listen, die du zu einer großen zusammenführen willst.
Dafür bieten Listen in Python die Funktion extend().
An einer bestehenden Liste kannst du einfach extend(neue_liste) aufrufen und die neue Liste übergeben. Python kümmert sich dann selbst darum, die beiden Listen zu einer großen zusammenzuführen.
import csv
header = []
daten = []
with open('dateien/mitarbeiter_1.csv', 'r') as mitarbeiter_daten:
reader = csv.reader(mitarbeiter_daten, delimiter=',')
header = next(reader)
daten = [row for row in reader]
with open('dateien/mitarbeiter_2.csv', 'r') as mitarbeiter2_daten:
reader = csv.reader(mitarbeiter2_daten, delimiter=',')
# Header ist schon vorhanden, den brauchen wir nicht mehr
next(reader)
# die alten Daten sollen nicht überschrieben werden -> extend
daten.extend([row for row in reader])
with open('ergebnis.csv', 'w') as ergebnis_daten:
writer = csv.writer(ergebnis_daten, delimiter=',')
# erst wird der header geschrieben
writer.writerow(header)
# dann die ganzen Daten
writer.writerows(daten)
Das war’s auch schon. So einfach kannst du zwei CSV Dateien zusammenführen. Das funktioniert natürlich auch für beliebig viele CSV Dateien. Für jede weitere Datei musst du einfach nur einen weiteren with open() Block einfügen und mit extend() deine Daten erweitern. Am Ende schreibst du alles in deine Ergebnisdatei und schon hast du eine große Datei mit einer Kopfzeile und ganz vielen Daten.
Das soll’s für heute gewesen sein.
Du kannst jetzt CSV Dateien mit Python Standardmitteln einfach auslesen und in neue Dateien schreiben.
Im nächsten Artikel zeige ich dir dann, wie du einfach alle Dateien in einem Verzeichnis zusammenführst – egal wie viele es sind!
Kurse
Code Challenges und YouTube Videos führen nicht immer zum gewünschten Erfolg.
Manchmal ist es besser, gezielt und strukturiert durch ein Thema zu arbeiten.
Schau dich einfach mal bei meinen Kursen um.
Ohne lästiges Blah Blah steigen wir direkt in das Thema ein und behandeln alles, was du brauchst.
Ingo Janssen ist ein Softwareentwickler mit über 10 Jahren Erfahrung in der Leitung seines eigenen Unternehmens.
Er studierte Wirtschaftsinformatik an der TH Deggendorf und hat Softwareentwicklung an der FOM Hochschule in München unterrichtet.
Ingo hat mit einer Vielzahl von Unternehmen zusammengearbeitet, von kleinen und mittelständischen Unternehmen bis hin zu MDAX- und DAX-gelisteten Unternehmen.
Ingo ist leidenschaftlich daran interessiert, sein Wissen und seine Expertise mit anderen zu teilen. Aus diesem Grund betreibt er einen YouTube-Kanal mit Programmier-Tutorials und eine Discord-Community, in der Entwickler miteinander in Kontakt treten und voneinander lernen können.
Sie können Ingo auch auf LinkedIn, Xing und Gulp finden, wo er Updates über seine Arbeit teilt und Einblicke in die Tech-Branche gibt.
YouTube | Discord | LinkedIn | Xing | Gulp Profile