Tabellen aus CSV Dateien in SQLite Datenbanken importieren
@ThoSchoo: Ich wüsste nicht wie man das noch einfacher demonstrieren könnte warum das nicht funktioniert. Du versuchst im Programm auf einen Schlüssel zuzugreifen den es in dem Wörterbuch nicht gibt (→ `KeyError`) weil die Schreibweise in der CSV-Datei eine andere ist und `dict` nun mal auf Gleichheit testet wenn man über einen Schlüssel zugreift.
Code: Alles auswählen
import csv
import sqlite3
con = sqlite3.connect("LGORT")
cur = con.cursor()
cur.execute("CREATE TABLE invoice (LGORT_ID INTEGER, City TEXT, WERKS_ID INTEGER);")
with open('tbl_LGORT.csv') as input_file:
reader = csv.DictReader(input_file)
to_db = [(i["LGORT_ID"], i["City"], i["WERKS_ID"]) for i in reader]
cur.executemany("Insert into invoice (LGORT_ID, City, WERKS_ID) Values (?, ?, ?);", to_db)
con.commit()
KeyError: 'LGORT_ID'
Leider doch ..
Zuletzt geändert von Anonymous am Dienstag 12. Januar 2016, 00:10, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
- pillmuncher
- User
- Beiträge: 1484
- Registriert: Samstag 21. März 2009, 22:59
- Wohnort: Pfaffenwinkel
@ThoSchoo:
1) Setz bitte den Code in Zukunft in CodeBox-Tags. Direkt über dem Eingabefenster ist eine Dropdown-Box ("Code auswählen"). Da drauf klicken, die Buchstaben p und y eingeben und Enter drücken, schon hast du ein Paar CodeBox-Tags. Da kommt der Code rein.
2) Kann es sein, dass in deiner Datei tbl_LGORT.csv in der ersten Zeile etwas anderes steht, als LGORT_ID etc? Stehen da überhaupt Spaltennamen? Oder gleich in der ersten Zeile ein Datensatz? Falls letzteres, musst du die gewünschten Spaltennamen beim Aufruf von csv.DictReader() als Argument (zB. in einer Liste) übergeben. Wie das genau geht, steht in der Doku.
1) Setz bitte den Code in Zukunft in CodeBox-Tags. Direkt über dem Eingabefenster ist eine Dropdown-Box ("Code auswählen"). Da drauf klicken, die Buchstaben p und y eingeben und Enter drücken, schon hast du ein Paar CodeBox-Tags. Da kommt der Code rein.
2) Kann es sein, dass in deiner Datei tbl_LGORT.csv in der ersten Zeile etwas anderes steht, als LGORT_ID etc? Stehen da überhaupt Spaltennamen? Oder gleich in der ersten Zeile ein Datensatz? Falls letzteres, musst du die gewünschten Spaltennamen beim Aufruf von csv.DictReader() als Argument (zB. in einer Liste) übergeben. Wie das genau geht, steht in der Doku.
In specifications, Murphy's Law supersedes Ohm's.
@Sirius3
JAAA.. das scheint das Problem gewesen zu sein ..
Nun gibt er mir allerdings beim auslesen ein "u" vor der City !?
JAAA.. das scheint das Problem gewesen zu sein ..
Code: Alles auswählen
con = sqlite3.connect("LGORT")
cur = con.cursor()
cur.execute("CREATE TABLE invoice (LGORT_ID INTEGER, City TEXT, WERKS_ID INTEGER);")
with open('tbl_LGORT.csv') as input_file:
reader = csv.DictReader(input_file, delimiter = ";")
to_db = [(i["LGORT_ID"], i["City"], i["WERKS_ID"]) for i in reader]
cur.executemany("Insert into invoice (LGORT_ID, City, WERKS_ID) Values (?, ?, ?);", to_db)
con.commit()
- (1, u'Bramsche', 1)
(2, u'Bramsche', 1)
(3, u'Bramsche', 1)
@ThoSchoo: Die Spaltennamen der CSV-Datei kann man vom `DictReader`-Objekt abfragen. Die Spaltennamen einer Datenbanktabelle kann man über das `description`-Attribut auf Cursor-Objekten abfragen wenn man eine Abfrage aller Spalten einer Tabelle macht. Datenbankspezifisch gibt es in der Regel noch andere Wege an diese Information zu kommen, ohne eine Abfrage der Daten selbst zu machen. An der Stelle würde ich dann aber auf eine Abstraktion wie SQLAlchemy ausweichen.
Datenbankspalten würde ich übrigens in Kleinbuchstaben bennenen. Eigentlich sollten die „case insensitive“ sein, allerdings machen das nicht alle Datenbanken so oder lassen sich zumindest auch anders konfigurieren. Genau wie bei Bezeichnern in einem Programm sollte man sich auch auf eine natürliche Sprache beschränken und nicht eine Spalte in deutsch und eine andere in englisch benennen. Da kommt man schnell durcheinander.
Datenbankspalten würde ich übrigens in Kleinbuchstaben bennenen. Eigentlich sollten die „case insensitive“ sein, allerdings machen das nicht alle Datenbanken so oder lassen sich zumindest auch anders konfigurieren. Genau wie bei Bezeichnern in einem Programm sollte man sich auch auf eine natürliche Sprache beschränken und nicht eine Spalte in deutsch und eine andere in englisch benennen. Da kommt man schnell durcheinander.
@BlackJack Danke aber ich hab leider nicht sehr viel verstanden, von dem was du mir mitteilen wolltest
Da es mehrere CSV Dateien sind, die alle in einem Verzeichnis liegen und alle als einzelne Tabellen in eine Datenbank eingetragen werden sollen, habe ich mal das hier zusammengesucht und -gesetzt:
Hier scheitert es allerdings schon bei dem durchsuchen des Ordners :
Ich arbeite gerade auf einem Mac .. das Ganze soll allerdings am besten überall anwendbar sein
Da es mehrere CSV Dateien sind, die alle in einem Verzeichnis liegen und alle als einzelne Tabellen in eine Datenbank eingetragen werden sollen, habe ich mal das hier zusammengesucht und -gesetzt:
Code: Alles auswählen
import csv
import sqlite3
import os
import glob
db = ("Mockupdata")
con = sqlite3.connect(db)
cur = con.cursor()
# traverse the directory and process each .csv file
for csvfile in glob.glob(os.getcwd("", "*.csv")):
# remove the path and extension and use what's left as a table name
tablename = os.path.splitext(os.path.basename(csvfile))[0]
with open(csvfile, "rb") as inputfile:
reader = csv.reader(inputfile)
header = True
for row in reader:
if header:
# gather column names from the first row of the csv
header = False
sql = "DROP TABLE IF EXISTS %s" % tablename
cur.execute(sql)
sql = "CREATE TABLE %s (%s)" % (tablename,
", ".join([ "%s text" % column for column in row ]))
cur.execute(sql)
insertsql = "INSERT INTO %s VALUES (%s)" % (tablename,
", ".join([ "?" for column in row ]))
rowlen = len(row)
else:
# skip lines that don't have the right number of columns
if len(row) == rowlen:
cur.execute(insertsql, row)
con.commit()
cur.close()
con.close()
Code: Alles auswählen
for csvfile in glob.glob(os.getcwd("", "*.csv")):
TypeError: getcwd() takes no arguments (2 given)
Zuletzt geändert von Anonymous am Dienstag 12. Januar 2016, 18:47, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Schau dir mal die Fehlermeldung an und dann die Klammern in der betreffenden Zeile.
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
@ThoSchoo: Der `os.getcwd()`-Aufruf ist hier sowieso überflüssig.
Das Programm würde ja nun sämtliche Felder in der Datenbank vom Typ TEXT anlegen. Und Constraints wie NOT NULL oder PRIMARY KEY gehen auf diese Art und Weise ja auch nicht.
Warum gibt es in der Datei überhaupt Zeilen mit der falschen Länge?
Statt *in* der Schleife ständig zu prüfen ob man die erste Zeile vor sich hat oder nicht, würde man die erste Zeilen einfach *vor* der Schleife mit `next()` vom Reader-Objekt abfragen.
Das ganze ist mittlerweile komplex genug um es sinnvoll auf Funktionen aufzuteilen.
Bei der Gelegenheit kann man dann auch gleich das Hauptprogramm in eine Funktion stecken (üblicherweise `main()` genannt) und auf Modulebene damit dann keinen Code mehr haben der nicht Konstanten, Funktionen, oder Klassen definiert.
Das Programm würde ja nun sämtliche Felder in der Datenbank vom Typ TEXT anlegen. Und Constraints wie NOT NULL oder PRIMARY KEY gehen auf diese Art und Weise ja auch nicht.
Warum gibt es in der Datei überhaupt Zeilen mit der falschen Länge?
Statt *in* der Schleife ständig zu prüfen ob man die erste Zeile vor sich hat oder nicht, würde man die erste Zeilen einfach *vor* der Schleife mit `next()` vom Reader-Objekt abfragen.
Das ganze ist mittlerweile komplex genug um es sinnvoll auf Funktionen aufzuteilen.
Bei der Gelegenheit kann man dann auch gleich das Hauptprogramm in eine Funktion stecken (üblicherweise `main()` genannt) und auf Modulebene damit dann keinen Code mehr haben der nicht Konstanten, Funktionen, oder Klassen definiert.
@cofi
wenn ich es so schreibe :
gibt er mir das :
wenn ich es so schreibe :
Code: Alles auswählen
csvfile in glob.glob(os.getcwd(""), "*.csv"):
Code: Alles auswählen
for csvfile in glob.glob(os.getcwd(""), "*.csv"):
TypeError: getcwd() takes no arguments (1 given)
@BlackJack
mit dem `os.getcwd()` will ich ja mein Arbeitsverzeichnis aufrufen in mein die Dateien vorhanden sind
Wie gelange ich denn sonst in das Verzeichnis?
Es dürfte eigentlich keine Daten mit einer falschen länge geben
mit dem `os.getcwd()` will ich ja mein Arbeitsverzeichnis aufrufen in mein die Dateien vorhanden sind
Wie gelange ich denn sonst in das Verzeichnis?
Es dürfte eigentlich keine Daten mit einer falschen länge geben
@ThoSchoo: Die Fehlermeldung ist doch ziemlich deutlich. Die Funktion erwartet keine Argumente, Du übergibst aber ein Argument. Lass das sein.
Zum aktuellen Arbeitsverzeichnis muss man nicht gelangen, da ist man bereits. Das ist ja gerade die Bedeutung von „aktuellem Arbeitsverzeichnis“, das von dort aus alle relativen Pfadangaben gesucht werden.
Wenn es keine Zeilen mit falscher Anzahl von Feldern geben kann, warum ist dann eine Prüfung darauf im Programm?
Zum aktuellen Arbeitsverzeichnis muss man nicht gelangen, da ist man bereits. Das ist ja gerade die Bedeutung von „aktuellem Arbeitsverzeichnis“, das von dort aus alle relativen Pfadangaben gesucht werden.
Wenn es keine Zeilen mit falscher Anzahl von Feldern geben kann, warum ist dann eine Prüfung darauf im Programm?
So funktioniert es :
allerdings ist es so alles in TEXT
wie könnte ich das denn umschrieben damit es den jeweiligen DatenTypen erkennt ?
Code: Alles auswählen
import csv
import sqlite3
import os
import glob
db = ("Mockupdata")
con = sqlite3.connect(db)
cur = con.cursor()
# traverse the directory and process each .csv file
for csvfile in glob.glob( "*.csv"):
# remove the path and extension and use what's left as a table name
tablename = os.path.splitext(os.path.basename(csvfile))[0]
with open(csvfile, "rb") as inputfile:
reader = csv.reader(inputfile, delimiter = ";")
header = True
for row in reader:
if header:
# gather column names from the first row of the csv
header = False
sql = "DROP TABLE IF EXISTS %s" % tablename
cur.execute(sql)
sql = "CREATE TABLE %s (%s)" % (tablename,
", ".join([ "%s text" % column for column in row ]))
cur.execute(sql)
insertsql = "INSERT INTO %s VALUES (%s)" % (tablename,
", ".join([ "?" for column in row ]))
rowlen = len(row)
con.commit()
cur.close()
con.close()
wie könnte ich das denn umschrieben damit es den jeweiligen DatenTypen erkennt ?
Zuletzt geändert von Anonymous am Dienstag 12. Januar 2016, 20:01, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Grund: Quelltext in Python-Codebox-Tags gesetzt.