Seite 1 von 1
log parsen REGEX Zeilen SQLITE übergeben
Verfasst: Donnerstag 2. Dezember 2010, 17:11
von wannabe
Hallo Allerseits,
habe mich bislang geziert hier Fragen zu stellen, jetzt drückt es aber doch zu sehr, da ich nicht weiß wo anzusetzen ist:
Problem: ich parse ein Logfile und kann erfolgreich 3 wichtige Werte extrahieren, diese werden mittels print value als 3 Zeilen ausgespuckt:
06026104
0.1501
02484.796
Ich möchte diese Werte in SQLite Tabelle mit 4 Werten übergeben, der erste Wert ist die ID als prim.Key, die anderen 3 SPalten sollen gefüllt werden mit obigen Werten. SQLite-Fehlermeldung, die Tabelle hat ja 4 Spalten (eine ID, die soll doch aber SQLite selbst führen)
Nun weiß ich nicht, ob ich im die Werte nochmal vorbereiten muß, oder ob ich bei der SQLite-Eintragung ansetzen soll? Bin blutigster Anfänger und sehe mitunter Möglichkeiten nicht.
Hat jemand eine Idee?
Code: Alles auswählen
with open("verbrauch.log") as fp:
for line in fp:
match = re.search(r'(0\.0\.0|1\.6\.1|1\.8\.1)\(([0-9\.]+)', line)
if not match: continue
version, value = match.groups() #version ist zu vernachlässigen
#print value würde Ausgabe wie oben bringen
for item in value:
cursor.executemany("INSERT INTO tabellename values (?,?,?)", item)
# cursor.execute('INSERT INTO tabellename(sernr, peak, verb) values (?,?,?)', item)
# cursor.execute("INSERT INTO tabellename(sernr) values (?)",(item[0],));
# cursor.execute("INSERT INTO tabellename(peak) values (?)",(item[1],));
# cursor.execute("INSERT INTO tabellename(verb) values (?)",(item[2],));
fp.close()
conn.commit()
cursor.close()
conn.close()
Re: log parsen REGEX Zeilen SQLITE übergeben
Verfasst: Donnerstag 2. Dezember 2010, 18:48
von DaMutz
Code: Alles auswählen
cursor.execute('INSERT INTO tabellename(sernr, peak, verb) values (?,?,?)', item)
dies sollte funktionieren, wenn du einen Leerschlag zwischen tabellename und Klammer setzt.
Weitere Punkte:
- fp.close() ist nicht nötig, da die Datei bereits geschlossen ist.
für diese Zeile:
Code: Alles auswählen
version, value = match.groups() #version ist zu vernachlässigen
schreib doch lieber:
Code: Alles auswählen
value = match.groups()[1] #1. Spalte ist zu vernachlässigen
oder lösche die Klammer in der RegEx.
Re: log parsen REGEX Zeilen SQLITE übergeben
Verfasst: Donnerstag 2. Dezember 2010, 19:27
von HerrHagen
DaMutz hat geschrieben:für diese Zeile:
Code: Alles auswählen
version, value = match.groups() #version ist zu vernachlässigen
schreib doch lieber:
Code: Alles auswählen
value = match.groups()[1] #1. Spalte ist zu vernachlässigen
Ob das nun wirklich besser ist ist, wage ich mal stark zu bezweifeln...
vielen lieben Dank erst einmal für die Ratschläge!
Verfasst: Donnerstag 2. Dezember 2010, 20:15
von wannabe
ich hatte ja bereits die eigentliche Ausgabe notiert:
06026104
0.1501
02484.796
Die ursprüngliche Eingabe sah so aus, nur so am Rande:
1.8.1(02484.825)
1.8.1*32(02449.574)
1.8.1*31(02393.949)
1.8.1*30(02341.038)
trotz des Leerzeichenhinweises (danke, sowas sollte nicht passieren), bleibt es bei SQL-Fehl.meld.
Incorrect number of bindings supplied. The current statement uses 3, and there are 1 supplied Nur 1 Wert? Wie eigenartig.
ich habe einfach mal versucht die obige Ausgabe in einer Liste zu sortieren, mit selben Ergebnis.
Code: Alles auswählen
version, value = match.groups()
mylist.append(value)
for item in mylist:
Die Fehlermeldung ändert sich wenn ich die Spaltenbezeichnung weglasse:
Code: Alles auswählen
cursor.executemany('INSERT INTO energielog values (?,?,?)', item)
OperationalError: table energielog has 4 columns but 3 values were supplied
Da scheint mir die Übergabe zumindest zu klappen. Ich elaboriere jedoch an der sicher trivialen Frage, wie ist das mit der ID in SQLite-Tabelle? diesen fortlaufenden Schlüssel übergebe ich ja nicht, denn beim nächsten Durchlaufen des log-Parsens sind es andere Werte; .schema ist energielog (ID INTEGER PRIMARY KEY, kwh NUMERIC, peak NUMERIC, sernr NUMERIC)
Ihr seht, es ist durchaus verzwickt und ich weiß einfach nicht wo anzusetzen wäre. Es muß irgendwas mit dieser Listung auf sich haben.
Re: vielen lieben Dank erst einmal für die Ratschläge!
Verfasst: Donnerstag 2. Dezember 2010, 20:25
von EyDu
Hallo.
Wenn ich mich richtig erinnere, sollte es so funktionieren:
Code: Alles auswählen
cursor.executemany('INSERT INTO energielog values (?,?,?,?)', (None, x, y, z))
Die erste Spalte muss dabei als Primary Key gesetzt sein.
So spart man sich den überflüssigen Namen und den Index:
Re: log parsen REGEX Zeilen SQLITE übergeben
Verfasst: Donnerstag 2. Dezember 2010, 20:51
von noisefloor
Hallo,
@wannabe: Hast du noch den Befehl, mit dem die die Tabelle in der SQLite DB angelegt hast? Ich tippe im Moment mal drauf, dass du für die 1. Spalte kein "auto increment" angelegt hast.
Ansonsten kann du dir das auch via Kommandozeile anzeigen lassen
- DB-Datei mit SQLite(3) öffnen
- .schema Name_der_Tabelle
Gruß, noisefloor
sqlite autoincrement probleme ?
Verfasst: Donnerstag 2. Dezember 2010, 22:08
von wannabe
schlicht wie ich bin, habe ich mir den sqlitebrowser gegriffen zum Erstellen. Dort gibt es Autoincrement gar nicht, überhaupt scheint es bei SQLite durch ROWID ersetzt zu sein
http://www.indigorose.com/forums/thread ... ith-SQLITE
Scheinbar muß man einfach nur für Autoincrement, wie EyDu vorschlug, Null mitgeben. Jedoch bringt er
cursor.executemany('INSERT INTO energielog values (?,?,?,?)', (None, x, y, z))
NameError: name 'x' is not defined
was sollte bei .. x, y, z) eingetragen werden?
Danke noisefloor, wie bemerkt, scheinbar muß man kein auto increment anlegen (kann das überhaupt sein?)
.schema-Abfrage: CREATE TABLE energielog (ID INTEGER PRIMARY KEY, kwh NUMERIC, peak NUMERIC, sernr NUMERIC);
AkteX sag ich da nur.
Re: log parsen REGEX Zeilen SQLITE übergeben
Verfasst: Donnerstag 2. Dezember 2010, 22:12
von EyDu
Na die drei Wert die bei dir in "item" stehen. Da sollte man aber drauf kommen.
Oder:
Edit: Angst vor Prügel

Re: log parsen REGEX Zeilen SQLITE übergeben
Verfasst: Donnerstag 2. Dezember 2010, 22:59
von BlackJack
@EyDu: Könntest Du bitte ganz schnell das Prozentzeichen da weg editieren. Sonst gibt's Haue.

Re: log parsen REGEX Zeilen SQLITE übergeben
Verfasst: Donnerstag 2. Dezember 2010, 23:38
von EyDu
BlackJack hat geschrieben:@EyDu: Könntest Du bitte ganz schnell das Prozentzeichen da weg editieren. Sonst gibt's Haue.

Da war wohl noch jemand im String-Formatting-Modus

Re: log parsen REGEX Zeilen SQLITE übergeben
Verfasst: Freitag 3. Dezember 2010, 02:02
von wannabe
Moin,
leider hat das nicht geklappt:
Code: Alles auswählen
cursor.executemany('INSERT INTO energielog values (?,?,?,?)', ((None,) +i))
None wird als string gewertet
TypeError: can only concatenate tuple (not "str") to tuple
mache ich es so:
Code: Alles auswählen
cursor.execute('INSERT INTO energielog(sernr) values (?)', i)
cursor.execute('INSERT INTO energielog(peak) values (?)', i)
cursor.execute('INSERT INTO energielog(kwh) values (?)', i)
wird immerhin klaglos etwas eingetragen, leider von oben nach unten: mehrfach der letzte Wert als Zahlenfolge, verteilt über Zeilen.
Ich habe noch vieles andere ausprobiert, ich vermute die Liste der obigen Werte ist eher eine Art Tabelle, jedes Zeichen ist ein item - vorhin hatte ich auch eine Fehlermeldung wo 8 Values gemeldet wurden für 4 Spalten, 06026104 ist bspw. 8 Zeichen lang.
Ich geh mal schlafne, vl. kommt morgen die Eingebung:
Code: Alles auswählen
cursor.executemany('INSERT INTO energielog(sernr,peak,kwh) values (?,?,?)', i)
so schert sich immerhin Python nicht um die ID, aber i bzw. item stimmt halt nicht
Re: log parsen REGEX Zeilen SQLITE übergeben
Verfasst: Freitag 3. Dezember 2010, 06:30
von BlackJack
@wannabe: Lies mal die Dokumentation was der Unterschied zwischen `execute()` und `executemany()` ist. Insbesondere was die jeweils als zweites Argument erwarten und damit dann machen.
Re: log parsen REGEX Zeilen SQLITE übergeben
Verfasst: Freitag 3. Dezember 2010, 10:39
von noisefloor
Hallo,
nochmal zum Thema "autoincrement": SQLite kann das auf zwei Arten. Einmal wie du es jetzt machst (machen musst) oder man nimmt beim Anlegen der Tabelle "AUTOINCREMENT" Schlüsselwert dazu:
http://www.sqlite.org/autoinc.html
http://www.sqlite.org/faq.html
Gruß, noisefloor
Re: log parsen REGEX Zeilen SQLITE übergeben
Verfasst: Montag 6. Dezember 2010, 15:03
von wannabe
Hallo,
ich denke hier liegt ein Missverständnis vor. Wie ich bereits mutmaßte, ist die Ausgabe selbst problematisch, daher ist das Einsortieren in SQLite so schwierig.
06026104
0.1501
02484.796
Ich vermag es nicht, daß Python diesen als 3 konsekutive Zeilen liest, dann wäre das Füttern mit
Code: Alles auswählen
if not match: continue
version,value = match.groups()
mylist.append(value)
for item in mylist:
t = (item)
cursor.execute('INSERT INTO energielog(sernr) values (?)', [t])
cursor.execute('INSERT INTO energielog(peak) values (?)', [t])
cursor.execute('INSERT INTO energielog(kwh) values (?)', [t])
sicher auch kein Problem mehr. Immerhin werden nun die Werte reingeschreiben, leider Zeile a in Spalte1, Zeile 2 - Spalte 2 usf.
Irgendwie muß ich Python beibiegen, jede Zeile als einen Wert einzuspeisen.
Re: log parsen REGEX Zeilen SQLITE übergeben
Verfasst: Montag 6. Dezember 2010, 19:54
von noisefloor
Hallo,
hm? Hast du dir den mittels print mal ausgeben lassen, wie "item" bzw. "value" aussieht?
Gruß, noisefloor
Re: log parsen REGEX Zeilen SQLITE übergeben
Verfasst: Montag 6. Dezember 2010, 20:24
von wannabe
hab ich, danke fürs Antworten
Code: Alles auswählen
if not match: continue
version,value = match.groups() #[1]
print version,value
0.0.0 06026104
1.6.1 0.1501
1.8.1 02484.796
06026104
0.1501
02484.796
(die eigentlichen Werte)
Code: Alles auswählen
version,value = match.groups() #[1]
mylist.append(value)
for item in mylist:
t = (item)
print t[0:3]
bringt:
060
0.1
024
Python hat die Werte in Tabelle organisiert und statt Zeilen werden Werte in Spalten gewertet?
Übrigens funktioniert in meinem heutigen Beitrag zumindest die Zuweisung der Ergebnisse in SQLITE in ganzen "Strings", aber eben nicht korrekt.
Wert 1: 06026104
steht so in Zeile1 Spalte1 dann aber wieder in Zeile2 Spalte2 und Zeile3 Spalte3
Wert 2: 0.1501
taucht erstes mal in Zeile4 Spalte1 dann in Zeile5 Spalte2 wieder usf.
Logisch, daß geünscht ist, Wert1 in Spalte namens "Sernr"; Wert2 in Spalte "peak" und so weiter eingetragen wird.
Re: log parsen REGEX Zeilen SQLITE übergeben
Verfasst: Montag 6. Dezember 2010, 20:56
von BlackJack
@wannabe: Wenn die drei Einträge in `mylist` eine Zeile in der Datenbank ergeben sollen, dann verstehe ich nicht warum Du versuchst die in einer Schleife einzeln in die DB zu schreiben und dann auch noch nacheinander in alle drei Datenspalten!? Das ist doch total unsinnig!?
Die Bedingung mit dem `match` davor würde ich übrigens umdrehen. Also nicht testen ob kein Treffer und dann ``continue``, sondern testen ob Treffer und dann den Wert an die Liste anhängen. Wobei `mylist` kein guter Name ist.
Das ``t = (item)`` ist sinnfrei. Sowohl die Zuweisung an sich von einem nichtssagenden Namen an einen anderen nichtssagenden Namen, als auch die Klammern.
Wenn Du *einen* Datensatz eintragen willst, dann mach das mit *einem* ``INSERT``. Darin so viele Platzhalter wie Werte in die Zeile eingetragen werden sollen, und als Argument dann eine Liste mit so vielen Werten wie Platzhalter da sind.
log parsen REGEX Zeilen SQLITE übergeben funktioniert! :idea
Verfasst: Montag 6. Dezember 2010, 22:42
von wannabe
Hier das Gesamtskript:
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
import serial
import time
import re
import sqlite3
# serielle USB-Schnittstelle öffnen
ser = serial.Serial()
ser.baudrate = 300
ser.port = /dev/ttyUSB0
ser.timeout = 2
ser.parity = serial.PARITY_EVEN
ser.stopbits = serial.STOPBITS_ONE
ser.bytesize = serial.SEVENBITS
ser.open()
# Zählerabfrage initiieren mit /?!
ser.write("/?!")
time.sleep(0.001) #1ms war im cutecom eingestellt und hat funktioniert
ser.write("\r") #CR LF?
# sqlite Einbindung vorbereiten
connection = sqlite3.connect(w"/var/httpdocs/dabaPyTest.s3db")
cursor = connection.cursor()
extrakt = []
#theoretisch sollte nun Zähler antworten
ser.readlines(eol='!') = z
for line in z:
match = re.search(r'(0\.0\.0|1\.6\.1|1\.8\.1)\(([0-9\.]+)', line)
if match:
version,value = match.groups()
extrakt.append(value)
#print extrakt
cursor.execute('INSERT INTO energielog (sernr, peak, kwh) values (?, ?, ?)', extrakt)
ser.close()
cursor.close()
connection.close()
so klappt zumindest des Parsen des Logfiles und Einsortieren in SQLite.
Vielen, vielen Dank für die Hilfe und Hinweise, auch wenn ich mich mitunter sehr angestellt habe. Waren es doch meine ersten Python-Gehversuche.
(code verbessert - Dank für die Tips - hab ich weitere syntaxfehler übersehen? - Ich bin mir vor allem unsicher was ser.readlines anbelangt, obgleich ich vom Gefühl her meine es klappt so)
Re: log parsen REGEX Zeilen SQLITE übergeben
Verfasst: Montag 6. Dezember 2010, 23:35
von BlackJack
@wannabe: Öhm, das enthält mindestens drei Syntaxfehler, lässt sich also nicht übersetzen.
Die Objekte würde ich enger "gruppieren", also nicht ganz am Anfang schon die Verbindung zur Datenbank aufbauen und `extrakt` definieren wo das doch gegen Ende erst benötigt wird.
Die Attribute von `serial` kann man auch dem Konstruktoraufruf schon mitgeben.
Die 1.0 (Sekunden) passen nicht zum Kommentar (Millisekunden).
Wofür steht `fp`? Ist zumindest in C eine übliche Abkürzung für "file pointer" -- das passt semantisch nicht zu einer Liste mit Zeichenketten.
`cursor` und `connection` werden in der falschen Reihenfolge geschlossen.