mit Python csv in mysql einbinden

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
wfog3435
User
Beiträge: 11
Registriert: Donnerstag 8. August 2019, 08:46

Hallo,
ich bin Neuling in Sachen Python und probiere gerade den Inhalt einer csv-Datei in eine Datenbank ber Python-Script zu schreiben.

die Datenbank:
CREATE TABLE mytable(
time VARCHAR(19) NOT NULL PRIMARY KEY
,msg VARCHAR(30)
,codes VARCHAR(30)
,model VARCHAR(16) NOT NULL
,id INTEGER NOT NULL
,temperature_F NUMERIC(6,3) NOT NULL
,humidity INTEGER NOT NULL
);

die csv-Datei:
time,msg,codes,model,id,temperature_F,humidity
2019-08-08 08:14:55,,,inFactory sensor,142,59.300,82
2019-08-08 08:14:56,,,inFactory sensor,142,59.300,82
2019-08-08 08:14:56,,,inFactory sensor,142,59.300,82

das Python-Script:
#!/usr/bin/python
import sys
import mysql.connector
import csv

# Verbindung zur Datenbank
try:
connection = mysql.connector.connect (host = "localhost", user = "user", passwd = "password", db = "db")
except:
print ("Keine Verbindung zum Server")
sys.exit(0)

# Execution-Objekt erzeugen
cursor = connection.cursor()


# Daten aus csv
with open('r91.csv', "rt") as ifile:
read = csv.reader(ifile)
for row in read:
cursor.execute("INSERT INTO mytable(time,msg,codes,model,id,temperature_F,humidity) VALUES(?, ?, ?, ?, ?, ?, ?)", row)

connection.commit()

# Execution-Objekt schliessen
cursor.close()

# Verbindung schliessen
connection.close()

die Fehlermeldung:
Traceback (most recent call last):
File "r91_db.py", line 21, in <module>
cursor.execute("INSERT INTO mytable(time,msg,codes,model,id,temperature_F,humidity) VALUES(?, ?, ?, ?, ?, ?, ?)", row)
File "/usr/local/lib/python2.7/dist-packages/mysql/connector/cursor.py", line 558, in execute
"Not all parameters were used in the SQL statement")
mysql.connector.errors.ProgrammingError: Not all parameters were used in the SQL statement

ich hoffe mir kann jemand helfen.

Danke im Voraus.
Benutzeravatar
sparrow
User
Beiträge: 4202
Registriert: Freitag 17. April 2009, 10:28

Bitte benutze die Code-Tags wenn du Code postest. Das ist der </> Button im vollständigen Editor.

Wie viele Elemente sind denn jeweils in "row", wenn die Zeile ausgeführt wird?

Edit: Ach halt, das ist mySql. Da sind die Platzhalter keine '?' sondern '%s', wenn ich mich richtig erinnere.
wfog3435
User
Beiträge: 11
Registriert: Donnerstag 8. August 2019, 08:46

Hallo sparrow,

erstmal danke für die schnelle Antwort, ich habe die Platzhalter angepasst, mit dem row sollte bewirkt werden das die Kopfzeile ausgelassen wird.

jetzt bekomme ich folgende Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "r91_db.py", line 21, in <module>
    cursor.execute("INSERT INTO mytable(time,msg,codes,model,id,temperature_F,humidity) VALUES(%s, %s, %s, %s, %s, %s, %s)", row)
  File "/usr/local/lib/python2.7/dist-packages/mysql/connector/cursor.py", line 566, in execute
    self._handle_result(self._connection.cmd_query(stmt))
  File "/usr/local/lib/python2.7/dist-packages/mysql/connector/connection.py", line 537, in cmd_query
    result = self._handle_result(self._send_cmd(ServerCmd.QUERY, query))
  File "/usr/local/lib/python2.7/dist-packages/mysql/connector/connection.py", line 436, in _handle_result
    raise errors.get_exception(packet)
mysql.connector.errors.IntegrityError: 1062 (23000): Duplicate entry '2019-08-08 12:17:28' for key 'PRIMARY'
der Skript jetzt:

Code: Alles auswählen

#!/usr/bin/python 
import sys
import mysql.connector
import csv

# Verbindung zur Datenbank
try:
    connection = mysql.connector.connect (host = "localhost", user = "root", passwd = "blabla", db = "meine")
except:
    print ("Keine Verbindung zum Server")
    sys.exit(0)

# Execution-Objekt erzeugen
cursor = connection.cursor()


# Daten aus csv
with open('r91.csv', "rt") as ifile:
    read = csv.reader(ifile)
    for row in read:
        cursor.execute("INSERT INTO mytable(time,msg,codes,model,id,temperature_F,humidity) VALUES(%s, %s, %s, %s, %s, %s, %s)", row)
        
connection.commit()

# Execution-Objekt schliessen
cursor.close()

# Verbindung schliessen
connection.close()
wfog3435
User
Beiträge: 11
Registriert: Donnerstag 8. August 2019, 08:46

Vielleicht gibt es ja auch einen anderen weg, ich möchte rtl_433 -R 91 die ausgelesenen Werte in MySql schreiben.
Benutzeravatar
sparrow
User
Beiträge: 4202
Registriert: Freitag 17. April 2009, 10:28

Du hast die Spalte 'time' als Primärschlüssel angelegt und versuchst einen bereits vorhandenen Wert noch einmal hinein zu schreiben. Das funktioniert bei einem Primärschlüssel nicht - der ist ja gerade dafür da, einzigartig zu ein.
wfog3435
User
Beiträge: 11
Registriert: Donnerstag 8. August 2019, 08:46

Danke, daran lag es, leider schmeißt mein inFactory Sender die Werte immer vierfach raus, und die Kopfzeile von der csv wird leider nicht ausgeschlossen.
Aber zumindest habe ich die Datenbank jetzt befüllt!
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Ein INSERT pro Zeile ist alles andere als effizient. In der Regel gibt es für sowas eine Methode wie `executemany`. Noch besser wäre es aber gleich LOAD DATA zu benutzen, wenn du ohnehin schon eine CSV Datei hast bietet sich dass an.
Sirius3
User
Beiträge: 17768
Registriert: Sonntag 21. Oktober 2012, 17:20

@wfog3435: Anmerkungen zum Code.
Das Zeitfeld sollte vom Typ TIMESTAMP sein und kein VARCHAR.
Keine nakten Excepts. Durch Deine "Fehlerbehandlung" verhinderst Du effizient, dass jemand herausfinden kann, warum keine Verbindung hergestellt werden kann. Also weg damit.
Beim Lesen der csv-Datei solltest Du den Header separat lesen, und auch testen, ob in der Datei wirklich das steht, was Du erwartest.
Antworten