Puh... wo fängt man da an... oben
- Zeile 2: Trenne imports nicht per Komma! Besser zwei getrennte Zeilen.
- Allgemein: Code auf Modulebene, der da nicht hingehört! Verwende Funktionen und den ``if __name__ == "__main__"``-Hook:
Code: Alles auswählen
def main():
# Deinen Einstiegscode hier rein packen
if __name__ == "__main__":
main()
- Zeile 16 ist ein NoGo! Fange *niemals* alle Exceptions ab. Fange nur *die* Typen ab, die Du auch sinnvoll behandeln willst! So wirst Du auch die Meldung "Verbindungsproblem" erhalten, wenn es einen ganz *anderen* Fehler gab... was die Ursachenforschung wesentlich schwieriger macht, wie Du Dir ja jetzt leicht vorstellen kannst.
- Ob man das Anlegen der DB wirklich im Code stehen haben will, mag Geschmackssache sein. Ich persönlich mag das nicht und bevorzuge da separate SQL-Scripte.
- Aber auf jeden Fall gehört das Anlegen in mindestens eine separate Funktion!
- Überlege mal, wann die Schleife verlassen wird

(Und *wieso*, also aus welchem Grund! Und, ob dabei die Variable ``logged`` eine Rolle spielt!)
- Zeile 23 ist für die wahren Metaller... äh... "Boole-isten"... ``logged`` *ist* vom Typ ``bool``... "falscher" kann es nicht werden, man braucht den Vergleich also nicht! ``while`` prüft auf den *Wahrheitswert* des nachstehenden Ausdrucks. Ein boolescher Ausdruck kann *direkt* ausgewertet werden, ohne, dass man da Vergleiche anstellen müsste. Alle anderen Ausdrücke haben ebenfalls einen Wahrheitswert; Python ermittelt den dann *implizit*. Bei Integerwerten ist die "0" falsch, alles andere ist wahr, leere Strings sind *immer* falsch, alle anderen wahr, usw. Du kannst Dir das einfach angucken, indem Du Dir das mal per ``bool``-Funktion in einer Python-Shell anguckst, also z.B. ``bool("")`` und bool("foo")``...
Drum merke Dir: Vergleiche auf ``True`` oder ``False`` kann man sich *immer* sparen, da der Wert, gegen den man vergleicht, offenbar einen eigenen Wahrheitswert besitzen muss. Und dieser kann *immer* direkt ausgewertet werden.
- Generell würde man da eher ``while True`` schreiben, also die "klassische" Endlosschleife und diese dann an geeigneter Stelle mittels ``break`` verlassen.
- Zeilen 24 & 25: ``uname`` und ``upass`` sind doofe Namen... wieso das ``user`` abkürzen? Autocompletion existiert und auf die Bytes müssen wir beim Quellcode nicht mehr schauen wie noch vielfach in den 80er Jahren.
- Zeile 26: Doofer Name, weil Du eine Typinformation in den Namen verpackst, was Du ebenfalls unterlassen solltest. Vor allem ist die Zeile aber obsolet, weil mit der Liste nichts mehr gemacht wird!
- Zeile 27: Wieso baust Du eine Query, bei der Du etwas zurücklieferst, was Du bereits kennst? (also den Benutzernamen)

Da wäre ein ``SELECT COUNT(*) FROM...`` imho sinnvoller, bei dem man anschließend auf die Anzahl == 1 testen sollte.
- Zeile 28: Wäre da ein ``fetchone`` nicht sinnvoller? Ich hätte erwartet, dass es *niemals* zwei Benutzernamen mit denselben Passwörtern geben sollte... (Wobei die Struktur der DB auch suboptimal ist! Da sollte man schon einen unique constraint auf Benutzernamen und Passwort legen - sowie einen Index natürlich)
- Zeile 29: ``liste`` ist ein doofer Name! Da *kann* gar keine "Liste" herauskommen, sondern allenfalls eine Art Tupel (eben eine Ergebniszeile der Query). Benenne es also um.
- Zeile 30:

Was glaubst Du passiert da? Meinst Du, da kann überhaupt einmal etwas falsches herauskommen?

(Denk mal dran, *woher* ``liste`` stammt und was Du dann mit ``in`` überprüfst)
- Die Zeilen 40 & 41 gehören da natürlich auch nicht hin... eine Verbindung sollte man nur schließen, wenn sie auch aufgebaut werden konnte. Iirc unterstützen die DB2-API das Context Manager Protokoll, bzw. ganz simpel ``with``. (Analog zu Dateien ``with open(...) as f``). Ich bin gerade zu faul in der Doku nachzuschlagen

Insofern wäre das immer meine erste Wahl, denn da braucht man sich nicht mehr selber um das Schließen kümmern.
Mist, jetzt habe ich so lange editiert, dass BlackJack schneller war
