PostgreSQL Datenbank teile auslesen und bearbeiten

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Hypec
User
Beiträge: 183
Registriert: Mittwoch 1. August 2018, 16:11

Hallo,
ich hab recht neu angefangen mit postgreSQL zu arbeiten und hab des Script hier in einem Touturial gefunden und soweit verstanden das ich weiß wie es Funktioniert. Nun meine frage das script liest ja immer die kommplette Datenbank aus wie kann ich nur einen ausgewählten teil aus der Datenbank auslesen lassen und wie kann ich diesen anschließend weiter verarbeiten?

Code: Alles auswählen

from configparser import ConfigParser
import psycopg2
import config

def configsql(filename='database.ini', section='postgresql'):
    # create a parser
    parser = ConfigParser()
    # read config file
    parser.read(filename)
 
    # get section, default to postgresql
    db = {}
    if parser.has_section(section):
        params = parser.items(section)
        for param in params:
            db[param[0]] = param[1]
    else:
        raise Exception('Section {0} not found in the {1} file'.format(section, filename))
 
    return db
    
  def get_vendors():
    """ query data from the vendors table """
    conn = None
    try:
        params = configsql()
        conn = psycopg2.connect(**params)
        cur = conn.cursor()
        cur.execute("SELECT vendor_id, vendor_name FROM vendors ORDER BY vendor_id")
        print("The number of parts: ", cur.rowcount)
        row = cur.fetchone()
 
        while row is not None:
            print(row)
            row = cur.fetchone()
        cur.close()
    except (Exception, psycopg2.DatabaseError) as error:
        print(error)
    finally:
        if conn is not None:
            conn.close()  
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Hypec: Du musst den ausgewählten Teil halt in der SQL-Anweisung auswählen bzw. durch entsprechende Bedingungen einschränken. Und anstatt die Datensätze mit `print()` auszugeben halt irgendwie anders verarbeiten. Beide hängt konkret davon ab was Du auswählen und was Du anschliessend damit machen willst.

`Exception` in dem ``except`` ist ziemlich allgemein. Das würde ich da raus lassen. Im Grunde eigentlich gleich das ganze ``except``, denn so wirklich sinnvoll ist die ”Behandlung” dort nicht. Die erschwert nur die Fehlersuche, sonst nix.

Beim Namen `get_vendors()` würde man einen Rückgabewert erwarten.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Hypec
User
Beiträge: 183
Registriert: Mittwoch 1. August 2018, 16:11

Also ich schreib ein Datum und danach 6 Messwerte in die Datenbank. Ich möchte jetzt 1 oder 2 Messwerte aus einem auswählbaren Zeitraum aus der Datenbank holen und anschließend mit matplotlib in einer Grafik anzeigen lassen.
So in etwa sieht eine Zeile momentan aus :

Code: Alles auswählen

(68, '{"2018-11-29 20:26",43.70,24.60,44.20,24.10,620,"16.67\r\n"}')
In die Datenbank schreiben tu ich mit dieser Funktion:

Code: Alles auswählen

def insert_vendor(vendor_name):
    """ insert a new vendor into the vendors table """
    sql = """INSERT INTO vendors(vendor_name)
             VALUES(%s) RETURNING vendor_id;"""
    conn = None
    vendor_id = None
    try:
        # read database configuration
        params = configsql()
        # connect to the PostgreSQL database
        conn = psycopg2.connect(**params)
        # create a new cursor
        cur = conn.cursor()
        # execute the INSERT statement
        cur.execute(sql, (vendor_name,))
        # get the generated id back
        vendor_id = cur.fetchone()[0]
        # commit the changes to the database
        conn.commit()
        # close communication with the database
        cur.close()
    finally:
        if conn is not None:
            conn.close()
 
    return vendor_id
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Hypec: ich weiß nicht, was Du da für ein Tutorial verwendest, aber ini-Dateien sind so 90er Jahre.
Die while-Schleife zum Lesen der Datensätze sollte eine for-Schleife sein und das finally in dem auf eine vor-initialisiertes `conn` geprüft wird ist gruselig.

Neben einem Python-Tutorial solltest Du auch ein SQL-Tutorial durcharbeiten, um den Umgang mit SELECT-Statements und weiteren SQL-Befehlen zu lernen.

Code: Alles auswählen

def get_vendors(**params):
    """ query data from the vendors table """
    conn = psycopg2.connect(**params)
    try:
        cur = conn.cursor()
        cur.execute("SELECT vendor_id, vendor_name FROM vendors ORDER BY vendor_id")
        print("The number of parts: ", cur.rowcount)
        for row in cur:
            print(row)
        cur.close()
    finally:
        conn.close()
EDIT: wenn Du mehrere Datenbank-Funktionen hast, ist es umständlich in jeder eine Verbindung aufzubauen. Übergib ein Datenbankverbindungsobjekt als Parameter.
Zuletzt geändert von Sirius3 am Samstag 1. Dezember 2018, 22:25, insgesamt 1-mal geändert.
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Hypec: Was Du da als ”Zeile” bezeichnest sieht komisch aus. Wie kommt denn der zweite Wert in diesem Tupel zustande?
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Hypec
User
Beiträge: 183
Registriert: Mittwoch 1. August 2018, 16:11

@__blackjack__ so wie ich dich verstanden hab meinst du das Datum mit Uhrzeit das ist der Zeitpunkt wann der Server die messwerte empfangen hat.
Hypec
User
Beiträge: 183
Registriert: Mittwoch 1. August 2018, 16:11

@Sirius3 Wenn ich die Daten nicht in eine ini Datei schreibe soll ich sie dann in ein Dict schreiben oder wo hin?
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Hypec: Nein ich meine nicht das Datum, das ist ja nur ein Teil der komischen Zeichenkette die da das zweite Element in dem Tupel ist. Wie ist diese Zeichenkette entstanden? Das ist ja *ein* Wert, der aber mehrere Werte als Zeichenkette in keinem mir bekannten Standardformat enthält. Wie ist das zustande gekommen? Warum diese Wahl?
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Hypec
User
Beiträge: 183
Registriert: Mittwoch 1. August 2018, 16:11

Die Werte waren bis her durch ein komma getrennt in einem csv file gespeichert. Kannst du mir vlt. ein besseres Format empfehlen?
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Jeder Wert in der Zeile gehört in eine Datenbank Spalte. Und der letzte wert, der offensichtlich ein float ist, sollte natürlich auch als solches gespeichert werden. Bereinigt um die sinnlosen Newlines und Carriage Returns. Und der Zeitstempel natürlich auch als solcher.
Hypec
User
Beiträge: 183
Registriert: Mittwoch 1. August 2018, 16:11

Oke das ordentliche schreiben habe ich Jetzt hiermit geschafft jetzt ist nur noch die Frage wie ich die Daten so aslesen kann das mir die Daten aus einem Bestimmten Zeitraum in einer Grafik angezeigt werden?

Code: Alles auswählen

def insert_data(luftfeuchtigkeitdrin,temperaturdrin,luftfeuchtigkeitausen,temperaturausen,erdfeuchtigkeit,lux):
    my_date = datetime.datetime.now(pytz.timezone('Europe/Berlin'))
    fmt = '%Y-%m-%d %H:%M'
    conn = psycopg2.connect(benutzername etc)
    print ("Opened database successfully")

    cur = conn.cursor()

    cur.execute("INSERT INTO MESSDATEN (TIMESTAMP,LUFTFEUCHTIGKEITDRIN,TEMPERATURDRIN,LUFTFEUCHTIGKEITAUSEN,TEMPERATURAUSEN,ERDFEUCHTIGKEIT,LUX) \
        VALUES (%s, %s, %s, %s, %s, %s, %s)", (my_date.strftime(fmt) ,luftfeuchtigkeitdrin, temperaturdrin, luftfeuchtigkeitausen, temperaturausen, erdfeuchtigkeit, lux)) 

    conn.commit()
    print ("Records created successfully")
    conn.close()
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Hypec: psycopg2 kann direkt mit datetime-Instanzen umgehen. Zum Abfragen brauchst Du halt die passende WHERE-clause für das SELECT-Statement. Das wird in jedem SQL-Tutorial abgehandelt.
Hypec
User
Beiträge: 183
Registriert: Mittwoch 1. August 2018, 16:11

Das weiß ich aber ich will wisen wie ich sie jetzt in meine Matplot grafik bringe.
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Na da hast du doch den cursor mit den Ergebnissen, die kannst du in eine Liste einlesen, und die mit matplotlib verarbeiten.

Code: Alles auswählen

... # SQL aehnlich SELECT timestamp, wert FROM ....
zeitpunkte = []
werte = []
for zeitpunkt, wert in cursor:
      zeitpunkte.append(zeitpunkt)
      werte.append(wert)
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Hypec: warum zeigst Du dann irrelevanten Code und nicht den, der Dir Probleme macht??

@__deets__: oder kürzer:

Code: Alles auswählen

zeitpunkte, werte = zip(*cursor)
Hypec
User
Beiträge: 183
Registriert: Mittwoch 1. August 2018, 16:11

Ich hab das ganze jetzt gelöst das einzige Problem was ich bisher nicht lösen konnte is das mir bei dem ax.plot mit 2 Messwerten 4 Sachen im Label angezeigt werden anstatt 2 wenn ich den 2. Wert rausnehme werden mir im Label wie gewollt 2 Sachen angezeigt hat jemand vlt ne idee wie ich das ändern kann?

Code: Alles auswählen

PLOTS = {
    'luftfeuchtigkeit': {
        'title': 'Luftfeuchtigkeit',
        'ylabel': 'Luftfeuchtigkeit in %',
        'plots': [('Luftfeuchtigkeit innen'), ('Luftfeuchtigkeit ausen')]
    },
    'temperatur': {
        'title': 'Temperatur',
        'ylabel': 'Temperatur in °C',
        'plots': [("Temperatur innen"), ("Temperatur ausen")]
    },
    'erdfeuchtigkeit': {
        'title': 'Erdfeuchtigkeit',
        'ylabel': 'Erdfeuchtigkeit in %',
        'plots': [('Erdfeuchtigkeit')]
    },
    'lux': {
        'title': 'Lichtitensität',
        'ylabel': 'Lichtitensität in Lux',
        'plots': [('Lichtitensität(lux)')]
    },
}

@app.route('/image/<filename>', methods=['GET', 'POST'])
def data(filename):
    data_one = filename.split('.')[0]
    
    conn = psycopg2.connect()
    print ("Opened database successfully")

    cur = conn.cursor()

    cur.execute("SELECT TIMESTAMP, LUFTFEUCHTIGKEITDRIN, TEMPERATURDRIN, LUFTFEUCHTIGKEITAUSEN, TEMPERATURAUSEN, ERDFEUCHTIGKEIT, LUX  from MESSDATEN")

    rows = cur.fetchall()

    time = []
    wertone = []
    werttwo = []
    rowone = 1
    rowtwo = 2
    plot = PLOTS[data_one]

    if data_one == 'luftfeuchtigkeit':
        rowone = 1
        rowtwo = 3
    elif data_one == 'temperatur' :
        rowone = 2
        rowtwo = 4
    elif data_one == 'erdfeuchtigkeit' :
        rowone = 5
    elif data_one == 'lux' :
        rowone = 6
    else :
        print ("error")

    for row in rows:
        time.append(row[0])
        wertone.append(row[rowone])
        if data_one == 'luftfeuchtigkeit' or data_one == 'temperatur':
            werttwo.append(row[rowtwo])

    fig, ax = plt.subplots()
    if data_one == 'luftfeuchtigkeit' or data_one == 'temperatur':
        for label in plot['plots']:
            ax.plot(time, wertone, werttwo, label=label)
    else:
        for label in plot['plots']:
            ax.plot(time, wertone, label=label ) 
    ax.grid(True)
    fig.legend()
    ax.set_title(plot['title'])
    ax.set_ylabel(plot['ylabel'])
    fig.autofmt_xdate()

    buffer = io.BytesIO()
    plt.savefig(buffer, format = 'png')
    plot_data = buffer.getvalue()

    response = make_response(plot_data)
    response.headers['Content-type'] = 'image/png'
    return response
Antworten