View ändert sich - Ausgabe bleibt gleich

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
dll-live
User
Beiträge: 32
Registriert: Dienstag 11. August 2020, 09:25
Wohnort: CH

Hallo zusammen

Heute habe ich ein ganz eigenartiges Phänomen entdeckt.

Das Programm wird gestartet und fragt 5 mal eine View ab - Der Inhalt der View ändert sich während der Laufzeit, doch die Ausgabe bleibt immer gleich. Wieso ist das so?

Anbei noch mein Programm:

Code: Alles auswählen

#!/usr/bin/python3
# -*- coding: utf-8 -*-
#Sebang...

from sys import path
path.insert(0, '/home/p13_dani/Desktop/Support_Dateien')

from HilfsKlassen import SqlVerbindung
from time import sleep

MariaDB = SqlVerbindung("Entwicklung-a") # Laptop
Zeiger = MariaDB.Zeiger()

# == Funktionen ==

def db_sensoren_auslesen():
    try:
        query1 = "SELECT Abfrage_ID, Name, Status_Name FROM Nummer_Name_V"
        Zeiger.execute(query1)
        Ergebnis = Zeiger.fetchall()
    except:
        print("Abfrage Fehler query1 - darf eigentlich nicht passieren")
        Ergebnis = []
    return Ergebnis

# === Hauptprogramm ====

if __name__ == '__main__':
    Sensoren_dict = {}
    i = 1
    while i <= 5:
        print(i)
        Sensoren = db_sensoren_auslesen()
        for Sensor in Sensoren:
            if Sensor[0] not in Sensoren_dict:
                Sensoren_dict[Sensor[0]] = "{0}--{1}".format(Sensor[1], Sensor[2])
        print(Sensoren_dict)
        sleep(5)
        i = i + 1
    MariaDB.ende()
Über Antworten warum das so ist und was ich ggf dagegen tun kann freue ich mich.

Freundliche Grüsse
Daniel
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Weil deine Datenbank innerhalb einer Transaktion den Cursor von den Veränderungen isoliert. Was gut ist, weil Berechnungen sonst inkonsistent werden.

Zur Abfrage muss also immer ein neuer cursor her.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Module werden wie Funktionen und Variablennamen komplett klein geschrieben. Ein Modul sollten auch einen besseren Namen als nur HilfKlassen haben.
Funktionen müssen alles was sie brauchen per Argumente bekommen, benutze keine globalen Variablen.
Was soll die 1 bei query1?
Auch Tabellennamen sollten aussagekräftig sein, was soll Nummer_Name_V denn bedeuten?
Nackte excepts darf man nicht benutzen, weil sie auch typische Programmierfehler wie falsch geschriebene Variablen abfangen und so die Fehlersuche quasi unmöglich werden. Wenn Du nicht weißt, welche Exception Du wie abfangen willst, lass es ganz weg.
Das Hauptprogramm sollte in einer Funktion stehen, die man üblicherweise main nennt.
Variablennamen sollten keinen Typen enthalten.
Wenn die SqlVerbindung nur Methoden von Englisch auf Deutsch umwandelt, ist das eine schlechte Idee, weil dann nur alle nicht nur die Englische sondern auch die Deutsche Schreibweise lernen müssen, und damit mehr wissen müssen. fetchall hast Du dann nicht eingedeutscht?
Statt der while-Schleife benutzt man hier eine for-Schleife.
Kommentare sollten einen Mehrwert bieten, dass da Funktionen oder das Hauptprogramm stehen, sieht man am def, bzw. if __name__.
Ein Cursor erzeugt einen Snapshot der Datenbank, damit man ein konsistentes Bild hat, weshalb Cursor nur kurz leben dürfen.

Code: Alles auswählen

from contextlib import closing
from HilfsKlassen import SqlVerbindung
from time import sleep

def db_sensoren_auslesen(database):
    with closing(database.cursor()) as cursor:
        cursor.execute("SELECT Abfrage_ID, Name, Status_Name FROM Nummer_Name_V")
        return cursor.fetchall()

def main():
    with closing(SqlVerbindung("Entwicklung-a")) as database:
        sensoren_by_id = {}
        for i in range(5):
            sensoren = db_sensoren_auslesen()
            for abfrage_id, name, status_name in sensoren:
                if abfrage_id not in sensoren_by_id:
                    sensoren_by_id[abfrage_id] = f"{name}--{status_name}"
            print(sensoren_by_id)
            sleep(5)

if __name__ == '__main__':
    main()
dll-live
User
Beiträge: 32
Registriert: Dienstag 11. August 2020, 09:25
Wohnort: CH

Hallo @__deets__ und @Sirius3

Besten Dank für eure Antworten.
Ich sehe, ich habe noch sehr viel zu lernen.

Freundliche Grüsse
Daniel
dll-live
User
Beiträge: 32
Registriert: Dienstag 11. August 2020, 09:25
Wohnort: CH

Hallo ähmm

Habe mich wohl doch zu früh gefreut.

Habe das Script von @Sirius3 genommen, die "SqlVerbindung" gelöscht und die DB-Verbindung direkt im Script gemacht.

Leider ist das Ergebnis wie zuvor.
Die View ändert sich während der Laufzeit - Ausgabe bleibt identisch.

Hier noch der Code:

Code: Alles auswählen

from contextlib import closing
from time import sleep
from sys import path
import mysql.connector as mariadb

MariaDB = mariadb.connect(host="localhost", user="abcde", password="xyz", database="Arbeit", buffered=False)

def db_sensoren_auslesen(database):
    with closing(database.cursor()) as cursor:
        cursor.execute("SELECT Abfrage_ID, Name, Status_Name FROM Nummer_Name_V")
        return cursor.fetchall()

def main():
    with closing(MariaDB) as database:
        sensoren_by_id = {}
        for i in range(15):
            print(i)
            sensoren = db_sensoren_auslesen(database)
            for abfrage_id, name, status_name in sensoren:
                if abfrage_id not in sensoren_by_id:
                    sensoren_by_id[abfrage_id] = f"{name}--{status_name}"
            print(sensoren_by_id)
            sleep(5)

if __name__ == '__main__':
    main()
Was ist hier noch fehlerhaft?

Freundliche Grüsse
Dani
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wie sieht es aus wenn Du nach der Abfrage ein `commit()` machst um die Transaktion zu beenden?
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
dll-live
User
Beiträge: 32
Registriert: Dienstag 11. August 2020, 09:25
Wohnort: CH

Hallo @__blackjack__

Das commit() hat keinerlei einfluss. Ergebniss bleibt gleich.

Gruss Daniel
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Hast du ein commit auf der schreibenden Seite? Und was passiert, wenn du auch die Verbindung selbst jedes mal aufmachst und wieder schliesst? Das sollte so nicht bleiben, aber zumindest zum ausprobieren.
dll-live
User
Beiträge: 32
Registriert: Dienstag 11. August 2020, 09:25
Wohnort: CH

Ja, auf der schreibenden Seite habe ich ein commit gemacht (Eintrag mit phpmyadmin erstellt - und mit neuer Session kontrolliert).
Wenn das Programm neu gestartet wird, wird die view korrekt eingelesen.....
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Na wie gesagt, hast du probiert, die Verbindung immer wieder neu aufzumachen?
dll-live
User
Beiträge: 32
Registriert: Dienstag 11. August 2020, 09:25
Wohnort: CH

Hallo @__deets__

Das habe ich jetzt auch noch geprüft und das ist das einzige was funktioniert....

anbei noch der Code.

Code: Alles auswählen

from contextlib import closing
from time import sleep
import mysql.connector as mariadb

def db_sensoren_auslesen():
    database = mariadb.connect(host="localhost", user="benutzer", password="geheim", database="Arbeit", buffered=False)
    with closing(database.cursor()) as cursor:
        cursor.execute("SELECT Abfrage_ID, Name, Status_Name FROM Nummer_Name_V")
        ergebnis = cursor.fetchall()
        database.commit()
        database.close()
        return ergebnis

def main():
    print("Script gestartet")
    sensoren_by_id = {}
    for i in range(15):
        print(i)
        sensoren = db_sensoren_auslesen()
        for abfrage_id, name, status_name in sensoren:
            if abfrage_id not in sensoren_by_id:
                sensoren_by_id[abfrage_id] = f"{name}--{status_name}"
        print(sensoren_by_id)
        sleep(5)

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