Python: CSV to SQL

Mo, 13. Dezember 2021, Ralf Hersel

Python eignet sich hervorragend, um Daten zu verarbeiten. Diese liegen oft als CSV-Datei vor, die man aus einer Datenbank oder anderen Datenquelle extrahiert hat. Das Lesen einer CSV-Datei in Python ist mit drei Zeilen Code erledigt; man erhält eine Liste der Daten als Ergebnis. Manchmal möchte man jedoch mit SQL-Abfragen auf diese Daten zugreifen. Aus diesem Grund habe ich ein kleines Python-Modul geschrieben, welches ebendiese Abfrage ermöglicht.

Das Modul heisst CSVSQL und findet sich in meinem Git-Repository auf Codeberg. Die Version 0.01 bietet nur grundlegendes; ein weiterer Ausbau der Funktionalität ist geplant. Das Modul besteht aus der Klasse db, in der alle Methoden für bequeme SQL-Abfragen enthalten sind. Und so geht es:

Möchte man das Modul im eigenen Python-Programm verwenden, so importiert man zuerst die Klasse db mit diesem Befehl:

from csvsql import db

Voraussetzung dafür ist, dass man die Datei csvsql.py aus dem Repository heruntergeladen und ins Verzeichnis des eigenen Python-Programms kopiert hat. Eine Installation ist nicht notwendig. Im Repository befindet sich auch ein Skript, in dem die Verwendung des Moduls beispielhaft gezeigt wird; dieses Beispiel heisst csvsql_example.py und verwendet die CSV-Datei test.csv. Die README.md im Repository erklärt die Funktionsweise und Verwendung im Detail.

Nach dem Import des Moduls kann die Klasse db verwendet werden:

data = db('test.csv')    

Hier wird eine Instanz der Klasse db in der Objektvariablen data erzeugt. Bei der Instanziierung wird die zu lesende CSV-Datei übergeben. Es wird davon ausgegangen, dass die CSV-Datei eine Header-Zeile mit den Spaltennamen enthält. Diese kann man sich so anzeigen lassen:

col = data.get_header()  
print(col)
['Name', 'Team', 'Position', 'Height', 'Weight', 'Age']

Die Anzahl der Datensätze in der CSV-Datei kann man mit print(len(col)) anzeigen lassen. Möchte man nun einen SQL-Befehl auf die Daten absetzen, sieht das zum Beispiel so aus:

sql = f"SELECT Name, Position, {col[-1]} | WHERE Name LIKE 'Al%' ORDER BY {col[2]}"
rows = data.query(sql)

Zuerst wird das SELECT-Statement in die Textvariable sql geschrieben und danach mit data.query(sql) ausgeführt. Das Ergebnis erhält man als Liste in der Variablen rows. Auf den ersten Blick sieht der SQL-Befehl etwas seltsam aus. Das Pipe-Symbol | ist ein Platzhalter für FROM tablename, weil man a) nicht weiss wie die Tabelle heisst und b) das dem Modul überlassen kann. Die Spaltennamen können direkt im SQL-Statement verwendet werden 'Name, Position' oder aus der Headerliste genommen werden: {col[2]}.

Die Liste rows kann nun beliebig weiterverwendet werden:

for row in rows:  print(row)

('Alvin Colina', 'Catcher', '25.18')
('Albert Pujols', 'First Baseman', '27.12')
('Alex Rios', 'Outfielder', '26.03')
('Alfonso Soriano', 'Outfielder', '31.15')
...

Für die nächsten Versionen des Moduls plane ich diese Features:

  • Optionale Angabe von Datentypen. Zurzeit sind alle Spalten vom Typ TEXT.
  • Optionale Angabe einer zu indizierenden Spalte.
  • Möglichkeit, die Abfrage eine Liste oder ein Dictionary liefern zu lassen.
  • Vermeiden des Neueinlesens der CSV-Datei, falls sich am Inhalt nichts geändert hat.

Update: "Vermeiden des Neueinlesens" und "Abfrageergebnis als Dictionary" habe ich im Release 0.02 implementiert.

Up-Update: Das Modul kommt noch lange nicht mit allen CSV-Format zurecht. Da muss ich noch etwas Arbeit hineinstecken. Stay tuned on:

Quelle: https://codeberg.org/ralfhersel/csvsql