Datenbank als Liste in Liste auslesen

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
DMD
User
Beiträge: 123
Registriert: Sonntag 17. Mai 2015, 03:34

hey ho ich bins nur :)

ich hoffe wieder einmal auf hilfe:
ich würde gern aus meinem "übungscode":

Code: Alles auswählen

db = sqlite3.connect(datei)
    cursor = db.cursor()
    cursor.execute('''SELECT id, ktoNum, vorname, nachname, gebdat, wohnort, ktoStand, erstePause, zweitePause FROM adressenliste WHERE ktoNum=?''', (ktoNum,))

    liste = [[]]
    for column in cursor:
        konto = [objectname, column[6]]
        #print konto

        for i in konto:
            liste.append(konto)
        print liste

#print name

db.close()
print konto:
['10.07.2015', 4]
['11.07.2015', 10]
['12.07.2015', 5]
['13.07.2015', 65]
['14.07.2015', 789]

eine liste in einer liste erstellen, d. h.

Code: Alles auswählen

liste = [['10.07.2015', 0], ['11.07.2015', 10], ['12.07.2015', 5], ['13.07.2015', 65], ['14.07.2015', 789]]
.

das was ich nur hinbekomme, ist das hier:

print liste:
[[], ['10.07.2015', 0], ['10.07.2015', 0]]
[[], ['11.07.2015', 0], ['11.07.2015', 0]]
[[], ['12.07.2015', 0], ['12.07.2015', 0]]
[[], ['13.07.2015', 0], ['13.07.2015', 0]]
[[], ['14.07.2015', 789], ['14.07.2015', 789]]

ich verzweifle langsam.
kann mir jemand bitte helfen?
BlackJack

@DMD: Da ist weder der Quelltext lauffähig noch verstehe ich so wirklich die Frage.

`liste` wird eine Liste mit einer leeren Liste als Element zugewiesen. Falls Du damit irgend wie hoffst das auf magische Weise durch anhängen von Einzelementen verschachtelte Listen entstehen: Dem ist natürlich nicht so.

Edit: Nun ist mittlerweile noch etwas zur Frage hinzugekommen, was aber nicht zum Code passt.
DMD
User
Beiträge: 123
Registriert: Sonntag 17. Mai 2015, 03:34

ok, ok
hier der vollständige code:

Code: Alles auswählen

import os
import sqlite3
from Tkinter import *

try:
    dirname = 'C:\Users\DMD-OL\Desktop\Verwaltung Arbeitszeit\Monat'
    os.makedirs(dirname)
except:
    pass

ktoNum = 2

dirname = 'C:\Users\DMD-OL\Desktop\Verwaltung Arbeitszeit\Monat'
objects = os.listdir(dirname)
result = []
for objectname in objects:
    objectpath = dirname + "/" + objectname

    otype = "dir"
    if (otype == "all" or
        (otype == "dir"  and os.path.isdir(objectpath)  == True)):
        result.append(objectname)
    datei='%s\\adressenliste.db' % (objectpath)


    db = sqlite3.connect(datei)
    cursor = db.cursor()
    cursor.execute('''SELECT id, ktoNum, vorname, nachname, gebdat, wohnort, ktoStand, erstePause, zweitePause FROM adressenliste WHERE ktoNum=?''', (ktoNum,))

    liste = []
    for column in cursor:
        #konto = [objectname, column[0], column[1], column[2], column[3], column[4], column[5], column[6], column[7], column[8]]
        konto = [objectname, column[6]]
        print konto

db.close()

ich lese hier mehrere ordner mit jeweils einer datenbank aus.

print konto sieht so aus:
['10.07.2015', 5]
['11.07.2015', 2]
['12.07.2015', 11]
['13.07.2015', 65]
['14.07.2015', 789]

ich möchte print konto gern als liste in liste haben, also so:
print konto:

Code: Alles auswählen

  [['10.07.2015', 5],['11.07.2015', 2],['12.07.2015', 11],['13.07.2015', 65],['14.07.2015', 789]] #<-- das will ich 
BlackJack

@DMD: Und wo ist da nun das Problem? Du musst doch einfach nur das was Du ausgibst statt es auszugeben an die Liste anhängen.

Sonstiges: Die ganzen Namen die Du aus `Tkinter` importierst werden überhaupt nicht verwendet.

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

In einem ``try``/``except`` sollte möglichst wenig Code stehen, also insbesondere keiner der mit der erwarteten Ausnahme nichts zu tun hat. Die Zuweisung von `dirname` kann (fast) keinen Laufzeitfehler auslösen, gehört also vor den ``try``-Block. Ausserdem sollte man keine nackten ``except:``-Anweisungen ohne konkrete Ausnahme(n) verwenden die man dort auch erwartet und behandeln will. Das gilt noch stärker wenn die ”Behandlung” aus komplettem ignorieren der Ausnahme besteht. So schafft man sich Stellen im Programm an denen Fehler nur sehr schwer zu finden sind.

Die Backslashes in dem Pfadliteral zu `dirname` sollte man entweder ”escapen” oder ein ”raw”-Zeichenkettenliteral verwenden. Dieser Wert sollte auch nur einmal definiert werden. Wenn man den Pfad einmal ändert übersieht man sonst sehr leicht einmal eine der Definitionen und das Programm arbeitet dann teilweise mit falschen Pfaden.

Die Schreibweise von `ktoNum` entspricht nicht dem Style Guide for Python Code. Ausserdem sollte man Namen nicht unnötig abkürzen. `kontonummer` ist viel verständlicher.

`objects`, `objectname`, `objectpath`, und `otype` sind unpassende Namen für die Werte für die sie stehen. Namensgebung ist bei der Programmierung eine sehr wichtige Sache.

Zum verbinden von Pfadteilen verwendet man `os.path.join()`.

Dieser ganze `otype`-Kram ist überflüssig weil das Programm so nur funktioniert wenn der `listdir()`-Aufruf ausschliesslich Unterverzeichnisnamen liefert. Sobald eine normale Datei dabei ist fliegt man beim Versuch einen Pfadnamen für eine DB-Datei damit zu erstellen auf die Nase. Was unter Windows problematisch ist, weil dort zum Beispiel gerne mal Dateien mit Vorschaubildchen für Dateien vom System in Verzeichnissen angelegt werden die man sich mit dem Dateimanager anschaut. Dagegen sollte man sich also schützen.

`datei` ist keine Datei sondern ein Datei*name* beziehungsweise ein kompletter Pfad zu einer Datei.

Das schliessen der Datenbank steht an der falschen Stelle. So wird nur die *letzte* Datenbank explizit wieder geschlossen. Es würde sich die ``with``-Anweisung zusammen mit `contextlib.closing()` anbieten um das schliessen sicherzustellen.

`column` ist wieder ein falcher Name da der Wert nicht für eine Spalte sondern für einen ganzen Datensatz steht.

Warum wird eigentlich so viel selektiert wenn dann sowieso nur ein Wert genommen wird, und das dann auch noch über einen nichtssagenden Index?

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf8
import errno
import os
import sqlite3
from contextlib import closing


def main():
    base_path = r'C:\Users\DMD-OL\Desktop\Verwaltung Arbeitszeit\Monat'
    try:
        os.makedirs(base_path)
    except OSError as error:
        # 
        # Ignore if path already exists.
        # 
        if error.errno != errno.EEXIST:
            raise

    kontonummer = 2
    result = []
    for filename in os.listdir(base_path):
        database_path = os.path.join(base_path, filename)
        if os.path.isdir(database_path):
            result.append(filename)
            with closing(
                sqlite3.connect(os.path.join(database_path, 'adressenliste.db'))
            ) as database:
                cursor = database.cursor()
                cursor.execute(
                    'SELECT ktoStand FROM adressenliste WHERE ktoNum=?',
                    (kontonummer,)
                )
                liste = [[filename, row[0]] for row in cursor]
                print liste

    print result


if __name__ == '__main__':
    main()
DMD
User
Beiträge: 123
Registriert: Sonntag 17. Mai 2015, 03:34

danke für deine ganzen verbesserungen und deine zeit damit.
werd ich in ruhe durcharbeiten (bin halt noch laie). danke
leider is mein problem doch nicht ganz klar geworden:

anstatt dieser ausgabe für "print liste":

[['10.07.2015', 0]]
[['11.07.2015', 0]]
[['12.07.2015', 0]]
[['13.07.2015', 0]]
[['14.07.2015', 789]]

hätte ich gern EINE liste mit den einzelnen listenausgaben (oben) als elemente dieser einen liste:

[ ['10.07.2015', 0] , ['11.07.2015', 0] , ['12.07.2015', 0] , ['13.07.2015', 0] , ['14.07.2015', 0] ]

hab schon viel im netz geguckt, bin aber immer noch nicht auf die lösung gekommen.
das hier

Code: Alles auswählen

list1 = []
for i in range(10):
    temp = []
    for j in range(5):
        temp.append(j)
    list1.append(temp)
print list1
is zwar schön, lässt sich aber nicht vernünftig (durch mich) verwendet, da ich
ja aus einer datenbank auslese.
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

@DMD: ob Du jetzt selbst eine Liste `temp` mit einer for-Schleife füllst, oder die Liste konto aus column erzeugst, ist doch egal, das Problem, Elemente an eine Liste anhängen ist das selbe.
BlackJack

@DMD: Ich weiss nicht was Du dazu viel im Netz guckst, Du musst einfach verstehen wie Listen (und Schleifen) funktionieren, das kannst Du nur bedingt irgendwo nachlesen, denn die notwendigen Informationen hast Du bereits. Dafür muss man auch nicht irgendwo im Netz suchen, da reicht das Tutorial in der Python-Dokumentation.

Edit: Und falls bei meinem Skript (sofern es denn läuft) auch etwas falsches ausgegeben wird, musst Du Dir noch mal genau Gedanken über den Programmablauf machen, also wann welcher Name an welchen Wert gebunden ist und wo im Programmverlauf leere Datenstrukturen angelegt werden müssen und wo die Daten dann vollständig sind damit man sie ausgeben kann.

Wenn ich die Beispieldaten so sehe scheinen die interessanten Verzeichnisnamen Datumsangaben zu sein. Auch das kann und sollte man vielleicht prüfen, so das man nicht nur Verzeichnisse weiterverarbeitet und damit nicht über eventuell vorhandene Dateien stolpert, sondern das auch Verzeichnisse vorhanden sein dürfen die nicht dem Muster entsprechen. Ich würde da auch langsam darüber nachdenken das ganze auf Funktionen aufzuteilen, denn das ist jetzt für meinen Geschmack schon ziemlich an der Grenze von „zu viel auf einmal”.

Edit2: Falls Du Einfluss auf die Gestaltung der Verzeichnisnamen mit den Datumsangaben hast würde ich das auf das Muster ”Jahr-Monat-Tag” ändern damit man die Zeichenketten einfach sortieren kann mit der Standardsortierung und dabei dann auch gleich zeitlich die richtige Reihenfolge bekommt.
DMD
User
Beiträge: 123
Registriert: Sonntag 17. Mai 2015, 03:34

ok, aber die ausgabe ist ja so wie sie jetzt ist genau richtig,
ich kriegs eben nicht hin daraus eine große liste zu machen
BlackJack

@DMD: Also entweder ist die Ausgabe genau richtig, dann muss man nichts mehr ändern, oder Du willst am Ergebnis etwas ändern, dann ist aber die Ausgabe nicht richtig.

Wenn Du eine Liste mit allen Ergebnissen haben möchtest dann musst Du halt am Anfang eine Liste erstellen, die um alle Teilergebnisse erweitern, und am Ende dann ausgeben. Oder anderweitig weiterverarbeiten.
DMD
User
Beiträge: 123
Registriert: Sonntag 17. Mai 2015, 03:34

SUPER VIELEN DANK
das ist das was ich gebraucht habe :) :) :)
Wenn Du eine Liste mit allen Ergebnissen haben möchtest dann musst Du halt am Anfang eine Liste erstellen, die um alle Teilergebnisse erweitern, und am Ende dann ausgeben. Oder anderweitig weiterverarbeiten.
na klar, die liste ausserhalb setzten.

hier noch mal alles für alle zum nachvollziehen:

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf8
import errno
import os
import sqlite3
from contextlib import closing


def main():
    base_path = r'C:\Users\DMD-OL\Desktop\Verwaltung Arbeitszeit\Monat'
    try:
        os.makedirs(base_path)
    except OSError as error:
        #
        # Ignore if path already exists.
        #
        if error.errno != errno.EEXIST:
            raise

    kontonummer = 2
    result = []
    liste = []
    for filename in os.listdir(base_path):
        database_path = os.path.join(base_path, filename)
        if os.path.isdir(database_path):
            result.append(filename)
            with closing(
                sqlite3.connect(os.path.join(database_path, 'adressenliste.db'))
            ) as database:
                cursor = database.cursor()
                cursor.execute(
                    'SELECT ktoStand FROM adressenliste WHERE ktoNum=?',
                    (kontonummer,)
                )
                for row in cursor:
                    konto = [filename, row[0]]
                    liste.append(konto)
    print liste


if __name__ == '__main__':
    main()
DANKESCHÖN BlackJack!
Antworten