Seite 1 von 2
Programmabsturz trotz Exception handling
Verfasst: Montag 29. Dezember 2014, 23:18
von hwm
Hallo,
merkwürdiges Problem, aber ich komme einfach nicht dahinter, wahrscheinlich ist die Lösung trivial (Python3.3.2 auf Linux), ich hänge nur im Moment vollkommen im Schacht.
Folgendes Code Snippet:
Code: Alles auswählen
while True:
try:
devList = lnetatmo.DeviceList(authorization)
break
except:
print ("Netatmo server did not respond, will retry in 60 seconds")
time.sleep(60)
Das lnetatmo Modul geht über eine Json Schnittstelle an einen HTTP Server, Details spielen, denke ich mal, keine Rolle.
Das Prinzip sollte ganz einfach sein: Server antwortet nicht, keine Netzanbindung etc. (deshalb keine qualifizierte Exception Abfrage): 60 Sekunden warten, dann noch mal probieren.
Wenn ich nun den Netzstecker ziehe um das Coding zu testen, würde ich erwarten, dass der Programmablauf genau in die Exception springt, tut er aber nicht:
Traceback (most recent call last):
File "/usr/lib64/python3.3/urllib/request.py", line 1248, in do_open
h.request(req.get_method(), req.selector, req.data, headers)
File "/usr/lib64/python3.3/http/client.py", line 1061, in request
self._send_request(method, url, body, headers)
File "/usr/lib64/python3.3/http/client.py", line 1099, in _send_request
self.endheaders(body)
File "/usr/lib64/python3.3/http/client.py", line 1057, in endheaders
self._send_output(message_body)
File "/usr/lib64/python3.3/http/client.py", line 902, in _send_output
self.send(msg)
File "/usr/lib64/python3.3/http/client.py", line 840, in send
self.connect()
File "/usr/lib64/python3.3/http/client.py", line 1194, in connect
self.timeout, self.source_address)
File "/usr/lib64/python3.3/socket.py", line 417, in create_connection
for res in getaddrinfo(host, port, 0, SOCK_STREAM):
socket.gaierror: [Errno -2] Name or service not known
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "pyqt_netatmo.py", line 24, in <module>
authorization = lnetatmo.ClientAuth()
File "/home/ich/python3/pyqt_netatmo/lnetatmo.py", line 62, in __init__
resp = postRequest(_AUTH_REQ, postParams)
File "/home/ich/python3/pyqt_netatmo/lnetatmo.py", line 242, in postRequest
resp = urllib.request.urlopen(req, params).readall().decode("utf-8")
File "/usr/lib64/python3.3/urllib/request.py", line 156, in urlopen
return opener.open(url, data, timeout)
File "/usr/lib64/python3.3/urllib/request.py", line 469, in open
response = self._open(req, data)
File "/usr/lib64/python3.3/urllib/request.py", line 487, in _open
'_open', req)
File "/usr/lib64/python3.3/urllib/request.py", line 447, in _call_chain
result = func(*args)
File "/usr/lib64/python3.3/urllib/request.py", line 1283, in https_open
context=self._context, check_hostname=self._check_hostname)
File "/usr/lib64/python3.3/urllib/request.py", line 1251, in do_open
raise URLError(err)
urllib.error.URLError: <urlopen error [Errno -2] Name or service not known>
und ich bin wieder auf der Konsole, ohne das die print Anweisung ausgeführt wird.
Wie kann das sein?
Re: Programmabsturz trotz Exception handling
Verfasst: Montag 29. Dezember 2014, 23:42
von Sirius3
@hwm: Zeig doch bitte auch die Zeile, in der die Exception ausgelöst wird:
Re: Programmabsturz trotz Exception handling
Verfasst: Dienstag 30. Dezember 2014, 00:01
von hwm
Sirius3 hat geschrieben:@hwm: Zeig doch bitte auch die Zeile, in der die Exception ausgelöst wird:
Nun ja, da wird die Exception nicht ausgelöst, sondern in den Standardbibliotheken von Python3.
In lnetatmo sieht das so aus (Die im Traceback ausgewiesene Zeile 242 ist hier die Zeile 6):
Code: Alles auswählen
def postRequest(url, params):
if version_info.major == 3:
req = urllib.request.Request(url)
req.add_header("Content-Type","application/x-www-form-urlencoded;charset=utf-8")
params = urllib.parse.urlencode(params).encode('utf-8')
resp = urllib.request.urlopen(req, params).readall().decode("utf-8")
else:
params = urlencode(params)
headers = {"Content-Type" : "application/x-www-form-urlencoded;charset=utf-8"}
req = urllib2.Request(url=url, data=params, headers=headers)
resp = urllib2.urlopen(req).read()
return json.loads(resp)
Und weiter gehts dann mit den Python3 Bibliotheken, also hier die urllib.
Re: Programmabsturz trotz Exception handling
Verfasst: Dienstag 30. Dezember 2014, 00:26
von BlackJack
@hwm: Doch da wird eine der beiden Ausnahmen ausgelöst. Das sieht man ziemlich deutlich im Traceback. Was man dort nicht sieht ist irgendeine von den Zeilen die Du gezeigt hast, also wieso meinst Du *das* wäre die Quelle beziehungsweise der ``except``-Zweig dort sollte ausgeführt werden?
Re: Programmabsturz trotz Exception handling
Verfasst: Dienstag 30. Dezember 2014, 00:35
von hwm
Also ich sehe das so: irgendwo schmeißt die urllib eine Exception, weil keine Netzverbindung da ist, logisch. Das Modul lnetatmo (ist nicht von mir sondern ein auf Github gehostetes Modul als Schnittstelle zu Netatmo Wetterstationen) wirft keine Exception und fängt auch keine ab, also würde ich davon ausgehen, dass die Exception über den Stack bis zu meinem Programm durchgereicht wird. Dass scheint aber nicht zu funktionieren, und ich habe im Moment keine Ahnung, wieso nicht. Oder übersehe ich da etwas?
Re: Programmabsturz trotz Exception handling
Verfasst: Dienstag 30. Dezember 2014, 00:53
von BlackJack
@hwm: Die Zeile die Sirius3 sehen wollte beziehungsweise auch den Code drumherum ist doch aber von Dir, und genau die ist ja an der Ausnahme beteiligt. Dort wird `authorization` definiert und da der Code von dem Du behauptest er sei betroffen auch auf ein `authorization` zugreift sieht das, zumindest nach dem was Du uns bisher gezeigt hast, so aus als wäre gar nicht der Code wo Du das Problem vermutest betroffen sondern Code der zeitlich davor ausgeführt wird. Oder vielleicht auch parallel denn `sleep()` und Qt im Modulnamen legen ja nahe dass es sich um ein GUI-Programm handelt und da wird man ja im GUI-Thread nicht einfach so eine Minute schlafen und damit alles blockieren wollen.
Re: Programmabsturz trotz Exception handling
Verfasst: Dienstag 30. Dezember 2014, 01:03
von hwm
Halt halt, das qt im Namen ist irreführend, es ist kein GUI Programm sondern nur ein Bot, der alle 10 Minuten Daten abholt und in eine sqlite3 Datenbank schreibt. Hier das komplette Coding (sind nur etwas mehr als 100 Zeilen):
Code: Alles auswählen
#!/usr/bin/python3
# encoding=utf-8
import time
import sqlite3
import lnetatmo
# Make a connection to the database and check to see if it succeeded.
try:
conn = sqlite3.connect("netatmo.db")
cur = conn.cursor()
except Exception as e:
print("FATAL Netatmo: Database not found")
sys.exit()
def set_date_time(date):
if len(date) == 1:
return "0" + date
else:
return date
while True:
# 1 : Authenticate
authorization = lnetatmo.ClientAuth()
# 2 : Get devices list
while True: # funktioniert nicht
try:
devList = lnetatmo.DeviceList(authorization)
break
except:
print ("Netatmo server did not respond, will retry in 60 seconds")
time.sleep(60)
theData = devList.lastData()
for i in theData:
# check for new devices
zu_lesen = "SELECT * FROM geraete WHERE geraet = '" + i + "'"
cur.execute(zu_lesen)
res = cur.fetchall()
if not res:
zu_erfassen = "INSERT INTO geraete VALUES ('" + i + "')"
print (zu_erfassen)
cur.execute(zu_erfassen)
# get actual data from devices
mintemp = 0
maxtemp = 0
luftdruck = 0
geraeusch = 0
co2 = 0
luftfeuchtigkeit = 0
batterie = 0
temperatur = devList.lastData()[i]['Temperature']
timestamp = str(time.localtime()[0]) + set_date_time(str(time.localtime()[1])) + set_date_time(str(time.localtime()[2])) + '-' + set_date_time(str(time.localtime()[3])) + set_date_time(str(time.localtime()[4]))
print (i, timestamp)
try:
mintemp = devList.lastData()[i]['min_temp']
except:
pass
try:
maxtemp = devList.lastData()[i]['max_temp']
except:
pass
try:
luftdruck = devList.lastData()[i]['Pressure']
except:
pass
try:
geraeusch = devList.lastData()[i]['Noise']
except:
pass
try:
co2 = devList.lastData()[i]['CO2']
except:
pass
try:
luftfeuchtigkeit = devList.lastData()[i]['Humidity']
except:
pass
try:
batterie = devList.lastData()[i]['battery_vp']
# print(i, "Batteriestatus :", "OK" if int(batterie) > 5000 else "ersetzen" )
except:
pass
werte = (i, timestamp, temperatur, luftdruck, geraeusch, co2, luftfeuchtigkeit, batterie)
zu_erfassen = "INSERT INTO daten VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
cur.execute(zu_erfassen, werte)
timestamp = str(time.localtime()[0]) + set_date_time(str(time.localtime()[1])) + set_date_time(str(time.localtime()[2]))
zu_lesen = "SELECT * FROM minmaxtemperatur WHERE geraet = '" + i + "' AND datum = " + timestamp
cur.execute(zu_lesen)
res = cur.fetchall()
if not res or res[0][1] != timestamp:
zu_erfassen = "INSERT INTO minmaxtemperatur VALUES (?, ?, ?, ?)"
werte = (i, timestamp, mintemp, maxtemp)
cur.execute(zu_erfassen, werte)
elif res[0][2] != mintemp or res[0][3] != maxtemp:
zu_erfassen = "UPDATE minmaxtemperatur SET mintemp = " + str(mintemp) + ", maxtemp = " + str(maxtemp) + " where geraet = '" + i + "' and datum = " + timestamp
cur.execute(zu_erfassen)
while True:
try:
conn.commit()
break
except:
print ("Database seems to be locked, will retry in 60 seconds")
time.sleep(60)
time.sleep(600)
Re: Programmabsturz trotz Exception handling
Verfasst: Dienstag 30. Dezember 2014, 01:13
von BlackJack
@hwm: Und warum denkst Du die Ausnahme müsste in dem Quelltextabschnitt auftreten den Du am Anfang gezeigt hast? Das kann doch genau so gut ausserhalb auftreten und führt dann eben bei der Zeile 24 zu einer Ausnahme die nicht behandelt wird und das Programm abbricht. Also genau das was der von Dir gezeigte Traceback nahelegt. Das dürfte sogar wahrscheinlich(er) sein, denn ich vermute mal das die meiste Zeit in der Schleife das `sleep()` in der letzten Zeile benötigt.
Re: Programmabsturz trotz Exception handling
Verfasst: Dienstag 30. Dezember 2014, 01:19
von hwm
Weil das Problem jederzeit nachvollziehbar ist, wenn ich (bildlich gesprochen) das Netzwerkabel ziehe. Ansonsten läuft das Programm wunderbar, es macht genau das, was es soll.Aufgetreten ist das Problem nur mal, als der Netatmo Server nicht geantwortet hat (Wartung, down, whatever). Doof ist dann aber, dass das Programm abstürzt. Natürlich könnte ich einen Cronjob einrichten, der das Programm alle 10 Minuten starte, aber wenn Python schon diese Möglichkeiten bietet ... Oder ein anderes Script fragt regelmäßig nach, ob das Programm noch läuft und startet es nach, falls nicht ... Es gibt viele Möglichkeiten ...
Re: Programmabsturz trotz Exception handling
Verfasst: Dienstag 30. Dezember 2014, 09:57
von Sirius3
@hwm: bei so viel Sturheit hab ich gar keine Lust mehr zu antworten. Wenn der Traceback auf Zeile 24 verweist, suche ich natürlich in Zeile 29 nach dem Fehler.

Zum Authentizieren brauch ich ja auch keine Netzverbindung.
Trotzdem noch gut gemeinte Ratschläge zum Code: Einrücktiefe sollte 4 Leerzeichen sein, ist leichter lesbar. Was set_date_time macht, macht man normalerweise mit Stringformatierung, aber dazu später mehr. Die nächsten Zeilen überspringe ich, weil ich weiß ja schon, dass Du da keine Hilfe willst.
`lastData` liefert ein Dictionary zurück, also statt 7mal sich diese Struktur nochmal erzeugen zu lassen, sollte die for-Schleife so aussehen:
Zeile 38: SQL-Statements sollte man
nie von Hand zusammenbauen, dafür gibt es Platzhalter, wie Du in Zeile 87/88 ja schon gezeigt hast. Für die Zeilen 38-44 gibt es übrigens ein INSERT OR IGNORE, falls das geraet-Feld unique ist:
Code: Alles auswählen
cur.execute("INSERT OR IGNORE INTO geraete VALUES (?)", (geraet, ))
Timestamps können Datenbanken automatisch einfügen, zum Beispiel wenn man als Default CURRENT_TIMESTAMP angibt. Alternativ hilft einem die Stringformatierung:
Code: Alles auswählen
timestamp = "{:%Y%m%d-%H%M}".format(datetime.datetime.now())
Für die nächsten Zeilen kennen Dictionaries `get` anstatt nackte excepts, die besser nur einen KeyError abgefangen hätten:
Wenn geraet und datum in minmaxtemperatur zusammen einen unique-Constraint bilden, läßt sich Zeile 91-100 zu einem "INSERT OR REPLACE"-Aufruf zusammenfassen. Die ganzen SQL-Statements und timestamp richtig zu schreiben, sei dem Leser als Übung überlassen.
Re: Programmabsturz trotz Exception handling
Verfasst: Dienstag 30. Dezember 2014, 10:15
von BlackJack
@hwm: Ergänzend zu Sirius3: Wenn die Spalte für die Zeitangabe den SQL-Typ ``TIMESTAMP`` besitzt, dann würde ich keine Zeichenkette zurechtformatieren sondern einfach direkt ein `datetime.datetime`-Objekt verwenden.
Die Zeichenkettenformatierung des Zeitstempels die Du da gemacht hast ist übrigens nicht nur ein ”Schönheitsproblem” sondern ist auch fehlerhaft weil Du fünf mal die aktuelle Zeit abfragst, das ja aber nicht fünf mal die gleiche Zeit ist, denn die schreitet zwischen den Aufrufen ja fröhlich weiter voran, und somit kann diese aus fünf unterschiedlichen Zeitpunkten zusammengestückelte Zeichenkette in ungünstigen Fällen sogar sehr deutlich von der tatsächlichen Zeit abweichen.
Re: Programmabsturz trotz Exception handling
Verfasst: Dienstag 30. Dezember 2014, 11:10
von hwm
@Sirius3: danke, zu fortgeschrittener Zeit und nach 3 Gläschen Wein hatte ich Tomaten vor den Augen und mich auf die Zeile 29 konzentriert, warum auch immer. Natürlich muss die Exception in Zeile 24 zusätzlich abgefangen werden, funktioniert jetzt.
@Sirius3 und BlackJack: die weiteren Ratschläge nehme ich dankend an, bis auf einen: INSERT OR IGNORE kennt zwar Sqlite3, aber andere, z. B. Postgres, nicht, daher mache ich das immer so, falls man auf eine andere Datenbank umstellen möchte/muss.
Re: Programmabsturz trotz Exception handling
Verfasst: Dienstag 30. Dezember 2014, 11:52
von BlackJack
@hwm: Man könnte die Ausnahme statt zusätzlich für Zeile 24 auch einmal für den gesamten Schleifeninhalt behandeln.
Das ist ja immer so eine Frage ob man für ein bestimmtes DBMS programmiert und auch dessen ganzen Zusätze zu Standard-SQL verwendet, oder ob man versucht so zu programmieren, dass man das DBMS leicht wechseln kann. Da Du SQL direkt benutzt bin ich von ersterem ausgegangen. Wenn Du das DBMS leicht wechselbar machen/halten willst, dann kannst Du die DB API 2.0 sowieso nicht direkt benutzen denn die Platzhalter sind bei verschiedenen Datenbankadaptern unterschiedlich. Und wenn man sowieso schon eine Abstraktionsschicht benötigt, dann würde ich SQLAlchemy empfehlen statt sich so etwas selber zu basteln. Dann wird man auch gleich das schreiben von SQL als Zeichenketten los.
Re: Programmabsturz trotz Exception handling
Verfasst: Dienstag 30. Dezember 2014, 12:47
von Sirius3
@hwm: Das Problem mit Deiner Lösung ist eben, dass wenn der SELECT keinen Eintrag findet, das später, wenn der INSERT Befehl ausgeführt wird, nicht unbedingt mehr gelten muß, weil vielleicht ein anderer Prozess die Datenbank inzwischen geändert hat. Richtigerweise müßtest Du also erst die Tabelle sperren, dann SELECT und INSERT durchführen und die Tabelle wieder freigeben. Oder das einfachste, Du machst nur einen INSERT und wenn der fehlschlägt ignorierst Du das einfach, weil dann der Eintrag schon existiert. Ähnlich ist das ja bei der minmaxtemperatur Aktualisierung: erst ein INSERT und wenn der fehlschlägt, ein UPDATE.
Re: Programmabsturz trotz Exception handling
Verfasst: Dienstag 30. Dezember 2014, 17:24
von hwm
@Sirius3: Sicher, das wäre der korrekte Weg, aber es gibt nur einen Prozess der Updates auf die DB macht, daher muss ich mir darüber keine Gedanken machen.
@BlackJack: SQLAlchemy hielte ich für eine solch kleine Anwendung etwas Overkill. Sollte eine Umstellung auf z. B. Postgres nötig sein, dann werden eben aus den '?' '%s' gemacht.
Dank an euch beide, man lernt immer wieder hinzu (bzw. erinnert sich an Vergessenes).
Re: Programmabsturz trotz Exception handling
Verfasst: Dienstag 30. Dezember 2014, 17:43
von BlackJack
@hwm: Wieso wäre das Overkill? Es vereinfacht den Umgang mit verschiedenen DBMS. Man kann keine syntaktischen Fehler beim SQL mehr machen oder zumindest nicht mehr so einfach. Man hat keine Probleme mit SQL-Injections mehr, wie Dein Code momentan. Die Probleme die Du mit den ``SELECT *`` verursachst gibt es nicht mehr. Man kann bei DBMS die es unterstützen ”reflection” verwenden, braucht also keine Tabellenobjekte definieren. Andererseits *kann* man das machen, und sogar ORM-Klassen. Bei SQLAlchemy werden auch mehr Datentypen automatisch umgewandelt als beim SQLite-Modul. Zum Beispiel weiss das Modul aus der Standardbibliothek das man `datetime.datetime` auf ``TIMESTAMP`` abbilden kann, aber bei ``DATETIME`` wird das unverständlicherweise nicht gemacht.
Und wenn man aus den '?' '%s' macht dann funktioniert es ja nicht mehr mit SQLite.
Re: Programmabsturz trotz Exception handling
Verfasst: Dienstag 30. Dezember 2014, 19:05
von hwm
Overkill aus folgenden Gründen:
1. zu hoher Einarbeitungsaufwand im Verhältnis zu solch einem Miniprogramm.
2. Zur SQL Injections Problematik: klar, das ist schon ein Argument, aber doch nicht in einer kleinen Privatanwendung. Hier bestünde natürlich das Problem, dass vom Webserver, von dem ich die Daten abhole, "verseuchte" Inhalte kämen, die ich ungeprüft in meine lokale DB überführe. Sollte das der Fall sein, hätte ich (und der Admin des Webservers) ein anderes und größeres Problem. Trotzdem habe ich das Coding geändert, auch weil es einfacher und eleganter ist.
3. SELECT * sollte man sowieso vermeiden wenn es irgendwie geht, bei den beiden in meinem Coding ist es aber so, dass ich tatsächlich jeweils den kompletten Datenbanksatz benötige (wobei der eine ohnehin nur eine Spalte hat).
Und 4. (hat nichts mit Overkill zu tun): ich hätte Angst, dass meine SQL Kenntnisse schwinden.
SQLAlchemy werde ich mir aber auf jeden Fall anschauen.
Und jetzt habe ich mir auch noch eine passende GUI zur Visualisierung der Messwerte mit PyQT gebastelt:
http://postimg.org/image/hw2eazh59/
Re: Programmabsturz trotz Exception handling
Verfasst: Dienstag 30. Dezember 2014, 20:36
von BlackJack
Ad 1.: Zu hoher Einarbeitungsaufwand? Da arbeitet man einmal ein Tutorial durch, wovon man dann bei jedem folgenden Programm etwas hat das eine relationale Datenbank verwendet. Und Programme haben auch die Tendenz mit der Zeit zu wachsen. Was heute als Miniprogramm anfängt, kann in zwei Jahren eine ausgewachsene Anwendung sein.
Ad 2.: SQL-Injektion ist auch bei Programmen ein Problem die nie angegriffen werden. Denn das ist ein Problem mit der geistigen Haltung des Programmierers. Die Lösung ist total einfach, da kann man nicht einmal von Mehraufwand sprechen. Wer das Problem kennt und *trotzdem* selber die Werte ins SQL formatiert sollte nicht programmieren dürfen.
Ad 3.: Noch hat die Tabelle nur eine Spalte. Gerade wenn sich das ändern sollte rächen sich solche '*'. Wobei ich mich gerade Frage wozu man die Tabelle mit *einer* Spalte benötigt? Wenn man die IDs (?) der vorhandenen Geräte wissen möchte kann man ja auch die `daten`-Tabelle abfragen. Andererseits sollte die `geraete`-Tabelle vielleicht nicht nur eine Spalte enthalten: Verwendest Du etwa eine Zeichenkette Geräte-Bezeichnung und speicherst die redundant in mehr als einer Tabelle? Und ich frage mich gerade was der Primärschlüssel von der `daten`-Tabelle ist?
Ad 4.: Wenn man nur die SQL-Abstraktion benutzt, dann ist relativ eindeutig wie das SQL aussehen wird, und man kann sich das ja auch jederzeit ausgeben lassen. Beim ORM auch, und da muss man das spätestens beim optimieren mal in das SQL schauen was da generiert wird.

Re: Programmabsturz trotz Exception handling
Verfasst: Dienstag 30. Dezember 2014, 22:02
von snafu
hwm hat geschrieben:Und 4. (hat nichts mit Overkill zu tun): ich hätte Angst, dass meine SQL Kenntnisse schwinden.
Um hier noch BlackJack zu ergänzen: Bei der SQL-Abstraktion werden dieselben Bezeichnungen verwendet wie im SQL, was ja auch Sinn macht, damit man sich schnell dort zurechtfindet. Es ist halt nur objektorientiert, d.h. du übermittelst die Befehle via Python-Syntax, anstatt einen reinen String für das SQL-Statement zu nutzen. Dein Einwand deutet IMHO stark darauf hin, dass du dir diesen Punkt schlicht noch nicht angeguckt hast.
Moderne datenbankbasierte Anwendungen nutzen häufig ein ORM - sei es in Python, in Java oder in einer anderen Sprache. Man macht definitiv nichts falsch, wenn man sich mal mit sowas näher befasst.
Re: Programmabsturz trotz Exception handling
Verfasst: Mittwoch 31. Dezember 2014, 00:55
von BlackJack
Dein Skript mal grob überarbeitet, ungetestet und nicht ganz Python 3 kompatibel, und mit leicht anderen Annahmen bei den Datenbanktabellen (englische Namen und künstliche IDs als Primärschlüssel):
Code: Alles auswählen
#!/usr/bin/env python
# coding: utf8
from __future__ import absolute_import, division, print_function
import sqlite3
from datetime import datetime as DateTime
from time import sleep
from urllib2 import URLError
import lnetatmo
def main():
connection = sqlite3.connect('netatmo.db')
cursor = connection.cursor()
while True:
try:
devices = lnetatmo.DeviceList(lnetatmo.ClientAuth())
except URLError:
print('Problem with Netatmo server, will retry in 60 seconds')
sleep(60)
else:
for name, values in devices.lastData().items():
cursor.execute(
'SELECT id FROM device WHERE name=?', (name,)
)
result = cursor.fetchone()
if result:
device_id = result[0]
else:
cursor.execute(
'INSERT INTO device(name) VALUES (?)', (name,)
)
device_id = cursor.lastrowid
timestamp = DateTime.now()
cursor.execute(
'INSERT INTO daten(device_id, `timestamp`, temperature,'
' pressure, noise, co_2, humidity, battery_vp)'
' VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
(
device_id,
timestamp,
values['Temperature'],
values.get('Pressure', 0),
values.get('Noise', 0),
values.get('CO2', 0),
values.get('Humidity', 0),
values.get('battery_vp', 0),
)
)
date = format(timestamp, '%Y-%m-%d')
cursor.execute(
'INSERT OR REPLACE INTO extrema(device_id, `date`,'
' min_value, max_value)'
'VALUES (?, ?, ?, ?)'
'WHERE device_id=? AND `date`=?',
(
device_id,
date,
values.get('min_temp', 0),
values.get('max_temp', 0),
device_id,
date,
)
)
while True:
try:
connection.commit()
break
except sqlite3.Error:
print(
'Database seems to be locked,'
' will retry in 5 seconds'
)
sleep(5)
sleep(600)
if __name__ == '__main__':
main()