Login-System mit .txt-Datei

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
mandus
User
Beiträge: 1
Registriert: Mittwoch 19. Mai 2021, 20:10

Hey Freunde,
das hier ist mein erster Thread, ich bin auch neu im Bereich Python, also bei Fehlern bitte nicht soo sauer werden.
Dann komm ich mal zu meinem Problem. Ich möchte ein Login-System programmieren, welches Benutzername und Passwort in einer txt-Datei speichert und später zum einloggen ausließt. Hier der Code:


----------------------------------------------------------------------------------------------------


users = open("users.txt","a")
status = ""

def displayMenu():
status = input("Are you registered user? y/n? Press q to quit")
if status == "y":
oldUser()
elif status == "n":
newUser()

def newUser():
createLogin = input("Create login name: ")
users = open("users.txt","r")
if createLogin in users:
print("\nLogin name already exist!\n")
else:
users = open("users.txt","a")
createPassw = input("Create password: ")
users.write(createLogin)
users.write("\n")
users.write(createPassw)
print("\nUser created\n")

def oldUser():
login = input("Enter login name: ")
passw = input("Enter password: ")
users = open("users.txt","r")

for zeile in users:
if (login in zeile) and (passw in zeile):
print("\nLogged in!\n")
else:
print("Wrong password or non existing acc!")
while status != "q":
displayMenu()




----------------------------------------------------------------------------------------------------


Als Ausgabe kriege ich leider immer falsche Ausgaben. Es funktioniert einfach alles nicht. Könnt ihr mal gucken, ob es irgendwelche Fehler gibt(die es geben wird)?

Danke im Voraus
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

Das globale `users` wird gar nicht benutzt, kann also weg.
`status` ändert sich nie, da schreibt man also besser eine while-True-Schleife.
Funktionsnamen schreib man wie Variablennamen komplett mit Kleinbuchstaben.
Variablen sollten nicht nach Tätigkeiten benannt werden. createLogin -> login_name
Dateien, die man öffnet sollte man auch wieder schließen, am besten mit dem with-Statement.
Ein Zeileende-Zeichen ist dazu da, dass es am Ende jeder Zeile steht.
Damit ist createLogin auch niemals in einer Zeile der Datei, weil jede Zeile ein Zeileendezeichen hat.
Benutze keine Abkürzungen, createPassw -> password.
Die Überprüfung in oldUser ist fehlerhaft, weil Loginname und Passwort bei Dir nicht in der selben Zeile stehen. Zudem möchte man ja nicht, dass irgendein Teil von Loginnname oder Passwort ein gültiges Passwort sind.
Benutze für das Speichern in der Datei ein etabliertes Datenformat. JSON, CSV, YAML
Ein Wörterbuch login -> passwort wäre praktisch.
Benutzeravatar
__blackjack__
User
Beiträge: 14056
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

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

Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).

Funktions- und Methodennamen beschreiben üblicheweise die Tätigkeit, die die Funktion durchführt. `newUser` und `oldUser` sind keine Tätigkeiten. Das wären Namen für Werte die Benutzer repräsentieren.

Dateien die man öffnet sollte man auch wieder schliessen. Am besten verwendet man die ``with``-Anweisung dafür.

Am Anfang wird die Datei geöffnet, das Dateiobjekt aber nirgends verwendet.

Bei Textdateien sollte man immer die Kodierung explizit angeben.

Man wiederholt keine Daten. So etwas wie den Dateinamen wo die Benutzerdaten gespeichert werden, definiert man *einmal* am Anfang des Moduls. Dann besteht keine Gefahr das man sich irgendwo mal vertippt und man kann den Dateinamen an einer Stelle ändern, und muss nicht anfangen das gesamte Programm zu durchsuchen. Immer mit der Gefahr, dass man nicht alle Stellen erwischt, oder nicht alle gleichartig ändert.

`status` in der Hauptschleife wird nie geändert, womit das effektiv eine Endlosschleife ist. `status` in der `displayMenu()`-Funktion ist ein anderes `status` das nur lokal innerhalb der Funktion existiert. Wenn der Wert beim Aufrufer bekannt sein soll, dann muss man den zurückgeben und der Aufrufer muss dann auch etwas damit machen.

Wenn man vor einer ``while``-Schleife einen Namen an einen Dummywert bindet damit die Schleife mindestens einmal durchlaufen wird, dann ist das besser eine ”Endlosschleife” die bei entsprechender Bedingung mit ``break`` verlassen wird.

Namen sollte man nicht kryptisch abkürzen. Wenn man `password` meint, sollte man nicht nur `passw` schreiben.

Die Klammern in der ``if``-Bedingung mit dem ``and`` sind überflüssig.

Zwischenstand:

Code: Alles auswählen

#!/usr/bin/env python3

USERS_FILENAME = "users.txt"


def register():
    login_name = input("Create login name: ")
    with open(USERS_FILENAME, "r") as users_file:
        if login_name in users_file:
            print("\nLogin name already exist!\n")
        else:
            with open(USERS_FILENAME, "a") as users_file:
                password = input("Create password: ")
                users_file.write(login_name)
                users_file.write("\n")
                users_file.write(password)
                print("\nUser created\n")


def login():
    login_name = input("Enter login name: ")
    password = input("Enter password: ")
    with open(USERS_FILENAME, "r", encoding="UTF-8") as users_file:
        for line in users_file:
            if login_name in line and password in line:
                print("\nLogged in!\n")
            else:
                print("Wrong password or non existing account!")


def display_menu():
    answer = input("Are you registered user? y/n? Press q to quit")
    if answer == "y":
        login()
    elif answer == "n":
        register()

    return answer


def main():
    while True:
        if display_menu() == "q":
            break


if __name__ == "__main__":
    main()
Das Problem ist, dass die beiden Funktionen zum Registrieren und Anmelden und das Dateiformat kaputt sind. Schreib keine neuen Funktionen solange die bisherigen noch nicht funktionieren. An diesen beiden Funktionen geht gar nichts.

Als erstes müsstest Du mal ein sinnvolles Dateiformat finden. Und dann kannst Du entscheiden ob Du eine Datei von Hand erstellen willst und die `login()`-Funktion schreiben möchtest, oder ob Du zuerst die `register()`-Funktion schreiben möchtest. Die jeweils andere solltest Du erst schreiben wenn die Funktion für die Du Dich entscheidest funktioniert.

Beide Funktionen würde ich so wie sie jetzt sind am besten einfach komplett löschen und von vorne anfangen.

Beim Testen darfst Du in beiden Fällen auch kein ``in`` verwenden. Du willst ja nicht wissen ob der Name (und das Passwort) *in* den gespeichert Daten vorkommt, sondern ob die komplett übereinstimmen. Sonst gibt man einfach "a" und "a" ein und hofft, dass es schon irgendeinen Benutzer geben wird, der diesen Buchstaben im Namen und im Passwort verwendet hat.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten