staging.inyokaproject.org

Per python-Skript ein neuen Datensatz in einen mySQL-Server eintragen

Status: Ungelöst | Ubuntu-Version: Ubuntu 18.04 (Bionic Beaver)
Antworten |

tzabbi

Anmeldungsdatum:
29. April 2018

Beiträge: Zähle...

Hallo Leute,

ich bin neu hier und hoffe ich mache alles richtig in meinem ersten Post. Das Problem ist wie folgt: Ich habe gestern 2 Raspis aufgesetzt einen mit Webserver und mariadb-Server, welchen ich über PHPmyadmin administriere. Der andere hat den DHT22 Sensor dran und soll die erfassten Daten in den mysql Server speichern. Die Verbindung wurde erfolgreich hergestellt, ich habe den mysql-Server für externe Zugriffe freigegeben und auch den User freigegeben. Das python Skript liefert auch keine Fehler zurück und führt alles aus. Nun sehe ich allerdings die Datensätze in der Tabelle meiner Datenbank nicht. Der einzige Hinweis, dass das Skript auch eine Verbindung mit dem mysql Server hatte ist, dass der primary key automatisch hochzählt. Das sehe ich wenn ich manuell über phpmyadmin ein Datensatz hinzufüge (spring nicht um 1 hoch sondern hat dann z.B. statt 4 auf 5 einen Sprung von 4 auf 9). Kann es sein, dass ich noch nicht alle Berechtigungen richtig für den Server eingerichtet habe?

Kennt Ihr das Problem und könnt mir eine Lösung verraten? Bei weiteren Infos stehe ich euch zur Verfügung!

Hier noch mein Python-Skript:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import Adafruit_DHT
import time 
import MySQLdb

from datetime import datetime
 
sensor = Adafruit_DHT.DHT22
 
# 1-Wire-Pin. BCM-Bezeichnung nutzen!
pin = 4
while True:
    humidity, temperature = Adafruit_DHT.read(sensor, pin)
    if humidity is not None and temperature is not None:
        #Sensordaten abfragen
        f = open('log.txt', 'a')
        f.write('Temp={0:0.1f}*C'.format(temperature))
        f.write(' ')

        f.write('Humidity={0:0.1f}%'.format(humidity))
        f.write(' ')
        f.write(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
        f.write('\n')
        f.close()
        #Verbindung zum mySQL-Server und Datensatz eintragen
        connection = MySQLdb.connect(host = "ip-adresse",
                                       db = "datenbank",
                                     user = "root",
                                   passwd = "toor")
        cursor = connection.cursor()
        print temperature
        print humidity
        cursor.execute("INSERT INTO daten (sender_id, temperature, humidity) VALUES (1, temperature, humidity)" )
        print  temperature
        print  humidity
        cursor.close()
        cursor.commit()
        time.sleep(60)
    else:
        print "Lesefehler. Erneut versuchen!"
        time.sleep(2)

Viele Grüße tzabbi

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4735

@tzabbi: Ich hätte ja fast gesagt das kann gar nicht sein, weil in Zeile 32 die Datenbank ganz klar meckern wird das temperature und humidity nicht definiert sind, aber MySQLdb/MySQL ”macht” das tatsächlich. Allerdings hatte ich danach Datensätze in der Tabelle. Und zwar mit ”Defaultwerten” für die undefinierten Namen. “Defaultwerte“ in Anführungszeichen, weil die Tabellenspalten selbst gar keine DEFAULT-Werte deklariert hatten. Trotzdem hat MySQL eine leere Zeichenkette für TEXT und eine 0 für INTEGER angenommen. Interessant… 😕

Irgendwelche Zeichenketten die zufällig Namen im Python-Programm entsprechen bekommen nicht auf magische Weise den Wert der an den Namen im Programm gebunden ist. Das ist auch logisch wenn man mal über die Folgen nachdenkt die das haben würde. Du erwartest doch hier (hoffentlich) auch nicht, das Hallo, Welt! ausgegeben würde:

1
2
name = 'Welt'
print('Hallo, name!')

Du musst für die Werte Platzhalter ins SQL schreiben und die eigentlichen Werte dann als Tupel oder Liste (oder eine andere Sequenz) als zweites Argument an Cursor.execute() übergeben. Wie in der MySQLdb-Dokumentation beschrieben.


Edit: PostgreSQL meckert wie erwartet wenn es Namen im SQL nicht gibt:

1
2
3
4
5
6
7
8
9
In [26]: c.execute('INSERT INTO person (age) VALUES (age)')
---------------------------------------------------------------------------
ProgrammingError                          Traceback (most recent call last)
<ipython-input-26-69ad213efcc9> in <module>()
----> 1 c.execute('INSERT INTO person (age) VALUES (age)')

ProgrammingError: column "age" does not exist
LINE 1: INSERT INTO person (age) VALUES (age)
                                         ^

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4735

@tzabbi: Ich habe da noch einen Fehler gefunden: commit() muss man auf der Verbindung aufrufen, auf Cursor-Objekten gibt es diese Methode nicht. Ausserdem schliesst Du die Verbindung nie explizit. In dem Zusammenhang ist die with-Anweisung zusammen mit contextlib.closing() auch sehr praktisch. Bei der Protokolldatei würde ich auch with verwenden.

Der erste Kommentar in der Schleife ist falsch, denn da werden die Sensordaten nicht abgefragt. Und der zweite Kommentar ist überflüssig — das dort die Verbindung zur Datenbank aufgebaut und die Daten eingetragen werden, steht dort als Code.

Die vielen write()-Aufrufe sind umständlich. Warum an der Stelle nicht *eine* Zeichenkette als Vorlage für alle drei Werte und dann nur ein write()-Aufruf‽

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#!/usr/bin/env python
# coding: utf-8
from __future__ import absolute_import, division, print_function
from contextlib import closing
from datetime import datetime
import time

import Adafruit_DHT
import MySQLdb
 
SENSOR_TYPE = Adafruit_DHT.DHT22
# 1-Wire-Pin. BCM-Bezeichnung nutzen!
SENSOR_PIN = 4
SENDER_ID = 1


def main():
    while True:
        humidity, temperature = Adafruit_DHT.read(SENSOR_TYPE, SENSOR_PIN)
        if humidity is not None and temperature is not None:
            with open('log.txt', 'a') as log_file: 
                log_file.write(
                    'Temp={0:0.1f}*C Humidity={1:0.1f}% {2:%Y-%m-%d %H:%M:%S}\n'
                        .format(temperature, humidity, datetime.now())
                )

            connection = MySQLdb.connect(
                host='ip-adresse', db='datenbank', user='root', passwd='toor'
            )
            with closing(connection):
                with closing(connection.cursor()) as cursor:
                    print(temperature)
                    print(humidity)
                    cursor.execute(
                        'INSERT INTO daten (sender_id, temperature, humidity)'
                        ' VALUES (%s, %s, %s)',
                        (SENDER_ID, temperature, humidity),
                    )
                connection.commit()
            time.sleep(60)
        else:
            print('Lesefehler. Erneut versuchen!')
            time.sleep(2)


if __name__ == '__main__':
    main()
Antworten |