Python Anmeldungscode optimieren (Kurzer Code)

HardtbeatShow

Cadet 4th Year
Registriert
Aug. 2020
Beiträge
96
Tagchen ^^ Ich lerne seit 2 Tagen Python und habe davor noch nie programmiert.
Ich habe mir einen kleinen Code geschrieben. Zweck ist eine Anmeldung.
Ich möchte den Username abfragen, danach das dazugehörige Password.
Es existiert nur ein Username im Code und zwar "testuser"
Das dazugehörige password ist "passwort123"
Mir war es wichtig das man den username unendlich oft eingeben kann aber die passwort abfrage maximal 3x funktioniert.
Nach 3x falsch kommt: "Versuche es später noch einmal"
Bei korrektem Passwort kommt: "Willkommen"

Aber der Code scheint mir ein bisschen lang zu sein... Das geht doch besser. Ich hoffe mir kann jemand einen Tipp geben :)

Danke!
1664787589238.png
 

Anhänge

  • 1664787565479.png
    1664787565479.png
    98,7 KB · Aufrufe: 183
1. Code bitte als code block als Text posten und nicht als Bild:

1664788909943.png


2. Ich würde vorschlagen den Code so zu schreiben dass keine User hart codiert in der Logik sind sondern von Außen konfigurierbar. Zum Beispiel als Text Datei die User und ihre Passwort Hashes speichert. Oder damit anfangen am Anfang des Skripts eine Liste möglicher User zu hinterlegen.

3. Schon wie in 2 erwähnt. Passwörter niemals im Klartext erwähnen sondern das Passwort gehasht und am Besten gesalted speichern. Da dein Testskript vermutlich nur zum Spielen ist spielt das jetzt keine Rolle, aber man würde damit schon einiges lernen.

4. Geeignete Fehlerausgaben wenn der User nicht existiert oder das Passwort falsch ist

5. Es ist leichter lesbar wenn man positive if-else Zweige definiert. Also if password == "...": und die Info der unbenutzten Zweige entweder für debug Ausgaben benutzt (Stichwort Logging) oder es dem User mitteilt

6. Schreibe kleine Methoden für die jeweiligen Teilaufgaben. Zum Beispiel: def get_user() -> str: und validate_password(user: str) -> boolean

7. Gerade bei User Inputs ist es oft sinnvoll die Input Logik von der Logik die den Input verarbeitet zu trennen. Das macht den Code leichter testbar

Ich hoffe die Tipps helfen dir etwas :)
 
Hey Danke dir ^^ Habe den Code überarbeitet. Bin sehr erstaunt was man innerhalb paar Stunden schon zaubern kann... wunderbar :D Und programmieren macht ja sau Spaß. Ich fühle mich als würde ich ein Strategiespiel spielen. Kreativität pur und dann dieser Optimierungswahn... hehe.
wegen dem Passwort hashen... damit kenne ich mich noch nicht aus. NOCH. Da gebe ich mir noch bisschen Zeit :)

Also:
Punkt 1 und 2 von dir dürfte ich erfüllt haben. User sind jetzt in ner Liste, genau wie passwörter.
Punkt 3 kommt irgendwann wenn ich mich mal damit beschäftige. (Bin in nem Kurs drinne. Das kommt vllt später einmal)
4. Fehler ausgabe bei Falschem Passwort und wenn benutzer nicht gefunden wurde.
5. Dürfte ich alles abgeändert haben
6. Das raff ich nicht^^
7. Ehm hab ich das erfüllt?^^

Der neue Code:


Python:
index_user = ""
index_password = ""
counter = 0
user_list = ["testuser", "testuser2"]
password_list = ["passwort123", "123passwort"]


while True:
    name = input("Benutzername: ")
    if name in user_list:
        index_user = user_list.index(name)
        break
    print("Benutzer konnte nicht gefunden werden")
    continue

while counter <3:
    password = input("Passwort: ")
    index_password = password_list.index(password)
    if index_password == index_user:
        break
    counter += 1
    print("Falsches Passwort. Achten Sie auf Groß- und Kleinschreibung")
    continue
if index_password == index_user:
    print("Willkommen")
else:
    print("Versuche es später noch einmal")
Ergänzung ()

Ah Nevermind. ich bekomme nen Error wenn ich nen falsches PW eingebe :D moment, muss ich fixen
 
Das ist schon besser.
Was ich mit kleinen Funktionen meinte: Statt die Logik jetzt so runter zu schreiben könnte man für die Teilaufgaben eine eigene Funktion schreiben. Nehmen wir mal den Teil der überprüft ob ein User existiert, also Schritt 1 einer Authentifizierung. Dann würde ich das so schreiben:

Python:
import sys
USERS = ["bob", "john"]
MAX_TRIES = 3

def prompt_user():
    for try_number in range(1, MAX_TRIES + 1):
        user_input = input("Username: ")
        if user_input in USERS:
            return user_input
        else:
            print(f"User does not exist: {user_input}. Tries left: {MAX_TRIES - try_number}")
    return None

def main():
    user = prompt_user()
    if not user:
        print("No valid user specified. Exiting")
        sys.exit(1)

if __name__ == "__main__":
    main()

Warum? Der Hauptfluss des Codes ist getrennt von der Logik. Wenn man sich main anschaut dann weiß man grob was passiert ohne jede Zeile Code zu lesen. Außerdem ist die Funktion prompt_user jetzt mehrfach aufrufbar, hat keine Seiteneffekte (so wie bei dir ein globaler counter) und gibt den gefundenen User zurück den man dann verwenden kann um mit dem Passwort Prompt weiter zu machen.
 
Oh mein Gott. Nicht nur den Error habe ich ausversehen eingebaut... Einen ganz üblen Fehler noch dazu. Und zwar war es total unwichtig ob das passwort zum Nutzer gelinkt ist oder nicht. hauptsache es war in der datenbank xD Also glaube ich... Ich blick selbst nicht mehr durch xD
Aber ich habe nen neuen Code.


also ich kann jetzt nen namen auswählen. dann wird direkt gesagt wenn der gar nicht in der datenbank ist. Wenn er korrekt ist geht es direkt weiter im programm. Und zwar wird vom eingegebenen Namen der Index gespeichert(ausgelesen in eine variable). Dann Passwort abfrage. Passwort wird mit dem richtigen passwort verglichen (Hat ja selben index, deshalb kann ichs easy auslesen lassen) Wenn das stimmt wird das programm beendet mit 'Willkommen, "name"'

Python:
password = ""
index = ""
counter = 0
user_list = ["testuser", "testuser2"]
password_list = ["passwort123", "123passwort"]

while True:
    name = input("Benutzername: ")
    if name in user_list:
        index = user_list.index(name)
        break
    print("Benutzer konnte nicht gefunden werden")
    continue

while counter < 3:
    password = input("Passwort: ")
    if password_list[index] == password:
        break
    else:

        counter += 1
        print("Falsches Passwort. Achten Sie auf Groß- und Kleinschreibung")
        continue

if password_list[index] == password:
    print("Willkommen", name)
else:
    print("Versuchen Sie es später noch einmal.")
Ergänzung ()

Wie ist eure Meinung dazu? :D Nicht schlecht für nen totalen Anfänger ^^ Hat mich allerdings 10 Jahre Lebenszeit gekostet
 
Ich finde das mapping von User zu seinem Passwort über ein Index eines Arrays unpraktisch und würde da eher sowas wie ein Dictionary benutzen:

Python:
USERS = {
    "bob": "secret1",
    "john": "secret2"
}

Prüfen ob ein es einen User gibt bleibt gleich if user in USERS.
Das Passwort von einem User zu bekommen ist intuitiver: USERS.get(user).
Bezüglich Coding Guidelines sollte man auch vermeiden den Typ der Variablen in den Namen zu kodieren.
Konkret sollte meiner Meinung nach user_list -> users heißen und password_list -> passwords. Aber wie schon davor angemerkt sollte man die Info eines Users, also den Namen sowie sein Passwort nicht in zwei verschiedenen unabhängigen Datenstrukturen speichern.
Ergänzung ()

Aber mit das Wichtigste ist meiner Meinung nach möglichst früh das Konzept einer Funktion zu verstehen und zu verwenden und Funktionen möglichst kurz zu halten um genau ein Problem zu lösen.
 
Zuletzt bearbeitet:
USERS.get(user) den get befehl habe ich noch nicht gelernt ^^ Bzw. glaube Operator nennt man das.
Typ werde ich nicht mehr in variablen kodieren. check. Ist das einfach ne ungeschriebene Regel oder hat dasn Sinn? Ich meine als fremder könnte ich dann leichter den Code lesen ^^ finde ich
Ergänzung ()

USERS = {
"bob": "secret1",
"john": "secret2"

kannst du mir das erkäutern was da genau passiert? bzw was da steht?
 
HardtbeatShow schrieb:
kannst du mir das erkäutern was da genau passiert? bzw was da steht?

Nennt man ein Dictionary. Das ist eine Datenstruktur die mit key, values arbeitet.
Statt bei einem Array mit einem integer index auf Elemente zuzugreifen kannst du bei einem Dictionary mit einem eigen definiertem Key auf Elemente zugreifen. Wenn wir jetzt ein Dictionary anlegen bei dem die Usernamen die keys sind und ihre Passwörter die Values dann erleichtert es die Zuordnung.

HardtbeatShow schrieb:
USERS.get(user) den get befehl habe ich noch nicht gelernt
Das nennt man nicht Operator, nein. Operatoren sind sowas wie + und -.
Die get Funktion bei Dictionaries gibt dir den Value des übergebenen Keys. Im Zweifel immer in den offiziellen Docs nachschauen. Das ist also einfach eine Member Methode eines Dictionaries. Eine andere Schreibweise wäre USERS[user].
 
Zurück
Oben