Python-Skript mit einem Befehl stoppen

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
GhastCraftHD
User
Beiträge: 6
Registriert: Freitag 20. März 2020, 07:54
Wohnort: Hamburg
Kontaktdaten:

Moin,
ich programmiere für die Schule gerade eine Art BIOS.
Ich würde gerne wissen, wie ich, wenn man den falschen Benutzernamen oder ein falsches Passwort eingibt, das Programm durch einen Befehl schließen lassen kann.

hier das Programm:

username = input("Bitte geben sie ihren Benutzernamen ein.")
if username == "GhastCraftHD"
print "Hallo GhastCraftHD"
password = input("Bitte gib dein Passwort ein.")
if password == "ghastcrafthd"
print "Zugriff gewährt!"
else:
print "Zugriff verweigert!"
#hier sollte das Programm dann beendet werden
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Naja im Moment beendet sich ja das Programm ja, weil es dann am Ende angekommen ist. Was möchtest du denn danach machen?

Hilft dir so etwas hier?

Code: Alles auswählen

import getpass

while True: #Endlosschleife
    username = input("Benutzername: ")
    passwort = getpass.getpass("Passwort: ") #"unsichtbare" Passwort eingabe
    if username == "GhastCraftHD" and passwort == "ghastcrafthd":
        print(f"Willkommen {username}")
        break #verlässt die Endlosschleife
    else:
        print(f"Falsche Anmeldedaten")
#hier kann das Programm dann weiter gehen
print("Anmeldung erfolgreich, Programm wird beendet.")

Sonstige Anmerkungen:

Beim Posten von Code bitte die Code-Tags (</>) im vollständigen Editor benutzen, sonst geht die Einrückung verloren.
Und der String hinter print gehört in Klammern, also print("mein string"), falls du noch Python 2.x verwendest solltest du auf Python 3.x updaten, da Python 2.x nicht mehr supported wird.
Hinter die Bedingung des Ifs gehören Doppelpunkte.
GhastCraftHD
User
Beiträge: 6
Registriert: Freitag 20. März 2020, 07:54
Wohnort: Hamburg
Kontaktdaten:

Also, mein Programm soll danach noch weiter gehen, ich habe auch schon weiter programmiert, ich möchte nur, dass sich das Programm beendet, wenn man die falschen Anmeldedaten eingibt.

Trotzdem Danke für deinen Vorschlag

Es würde mir auch noch helfen, wenn du mir sagst, wie man, wenn man bei der Frage: Willst du weiter rechnen, oder etwas anderes machen? Bei der Antwort nein wieder zur Aktivitäten Auswahl zurück geht.

Außerdem programmiere ich das ganze in einem Online-Editor und kann daher nur Datenbanken, die Turtle, Farben und Befehle ohne Importe benutzen.

Der Online Editor, den ich benutze ist: https://webtigerjython.ethz.ch/
Dort kann man aber auch Python 3 benutzen

Code: Alles auswählen

username = input("Bitte geben sie ihren Benutzernamen ein.")
if username == "Benutzer 1":
    print "Hallo Benutzer 1!"
    password4 = input("Bitte gib dein Passwort ein, Benutzer 1.")
    if password4 == "passwort":
        print "Zugriff gewährt!"
    else:
        print "Zugriff verweigert! Falsches Passwort!"
else:
    print "Unbekannter Benutzername"

#Aktivitätenauswahl
activity = input("Was möchtest du jetzt machen?")
if activity == "TR" or activity == "Rechnen" or activity == "Taschenrechner":
    print "Okay, jetzt wird gerechnet!"
    while True:
        num1 = input("Gib die erste Zahl ein: ")
        oper = input("Welche Rechenoperation soll durchgeführt werden? (+,-,/.,*): ")
        num2 = input("Gib die zweite Zahl ein: ")

        num1 = int(num1)
        num2 = int(num2)

        if (oper == "+"):
            print("Deine Rechnung:", num1, " + ", num2)
            print("Ergebnis:", num1 + num2)

        elif (oper == "-"):
            print("Deine Rechnung:", num1, " - ", num2)
            print("Ergebnis:", num1 - num2)

        elif (oper == "/"):
            print("Deine Rechnung:", num1, " / ", num2)
            print("Ergebnis:", num1 / num2)

        elif (oper == "*"):
            print("Deine Rechnung:", num1, " * ", num2)
            print("Dein Ergebnis:", num1 * num2)
        else:
            print("Deine Eingaben sind nicht gültig")

        jein = input("Willst du weiter rechnen, oder etwas anderes machen?")

        if jein == "Nein" or jein == "Nein" or jein == "Stopp":
            break
Zuletzt geändert von GhastCraftHD am Freitag 20. März 2020, 09:35, insgesamt 3-mal geändert.
GhastCraftHD
User
Beiträge: 6
Registriert: Freitag 20. März 2020, 07:54
Wohnort: Hamburg
Kontaktdaten:

Außerdem programmiere ich das ganze in einem Online-Editor und kann daher nur Datenbanken, die Turtle, Farben und Befehle ohne Importe benutzen.
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Warum heißt dass Passwort passwort4? Variablennamen sollten keine Nummern enthalten und vor allem keine zufälligen.
Um manche if-Bedingungen hast Du zu viele Klammern. Beim `activity` ist `in` hilfreich.
Bitte keine Abkürzungen. Beim Rechnen willst Du sicher nicht in die Oper gehen.
Bei umgangssprachlichen oder-Fragen ist die Antwort "Nein" nicht eindeutig: "Nein, ich möchte nichts anderes machen."
Was Du brauchst sind Funktionen, mit denen kannst Du den Programmfluss einfach durch `return` steuern:

Code: Alles auswählen

def login():
    username = input("Bitte geben sie ihren Benutzernamen ein.")
    if username == "Benutzer 1":
        print "Hallo Benutzer 1!"
        password = input("Bitte gib dein Passwort ein, Benutzer 1.")
        if password == "passwort":
            print "Zugriff gewährt!"
            return True
        else:
            print "Zugriff verweigert! Falsches Passwort!"
            return False
    else:
        print "Unbekannter Benutzername"
        return False

def rechnen():
    print "Okay, jetzt wird gerechnet!"
    while True:
        num1 = input("Gib die erste Zahl ein: ")
        operation = input("Welche Rechenoperation soll durchgeführt werden? (+,-,/.,*): ")
        num2 = input("Gib die zweite Zahl ein: ")

        num1 = int(num1)
        num2 = int(num2)

        if operation == "+":
            print("Deine Rechnung:", num1, " + ", num2)
            print("Ergebnis:", num1 + num2)
        elif operation == "-":
            print("Deine Rechnung:", num1, " - ", num2)
            print("Ergebnis:", num1 - num2)
        elif operation == "/":
            print("Deine Rechnung:", num1, " / ", num2)
            print("Ergebnis:", num1 / num2)
        elif operation == "*":
            print("Deine Rechnung:", num1, " * ", num2)
            print("Dein Ergebnis:", num1 * num2)
        else:
            print("Deine Eingaben sind nicht gültig")

        antwort = input("Willst du weiter rechnen, oder etwas anderes machen?")
        if antwort.lower() in ("nein", "stopp"):
            break

        
def main():
    if not login():
        # Programm beendet
        return
        
    #Aktivitätenauswahl
    activity = input("Was möchtest du jetzt machen?")
    if activity in ("TR", "Rechnen", "Taschenrechner"):
        rechnen()
                
main()
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Ich löse das immer mit Schleifen und breaks:

#edit: Denke aber die Version von Sirius ist besser, da bei mir schon etwas viel eingerückt wird.

Code: Alles auswählen

def do_math(first_number, operator, second_number):
    if operator == "+":
        return first_number + second_number
    if operator == "-":
        return first_number - second_number
    if operator == "/":
        return first_number / second_number
    if operator == "*":
        return first_number * second_number
    
def is_valid_login(username, passwort):
    if username == "GhastCraftHD" and passwort == "ghastcrafthd":
        return True
    else:
        return False
        
def main():
    username = input("Benutzername: ")
    passwort = input("Passwort: ")
    if is_valid_login(username, passwort):
        print("Anmeldung erfolgreich")
        activity = input("Was möchtest du jetzt machen?[TR/Rechnen/Taschenrechner]: ")
        if activity in ("TR","Rechnen","Taschenrechner"):
            print("Okay, jetzt wird gerechnet!")
            while True:
                first_number = int(input("Gib die erste Zahl ein: "))
                operator = input("Welche Rechenoperation soll durchgeführt werden? [+, -, /, *]: ")
                second_number = int(input("Gib die zweite Zahl ein: "))
                result = do_math(first_number, operator, second_number)
                print(f"{first_number} {operator} {second_number} = {result}")
                choice = input("Willst du weiter rechnen, oder etwas anderes machen? [Nein/Ja]: ")
                if choice == "Nein":
                    break

if __name__ == "__main__":
    main() 

@Sirius3:
Ich habe mal gehört man soll es vermeiden print Befehle in Funktionen zu nutzen und sollte die Ausgaben im main() machen basierend auf dem return der Funktion, stimmt das oder hat mir da jemand Quatsch erzählt?
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@GhastCraftHD: Bei Anmeldedaten sollte man den Benutzer immer erst beide Angaben, Name *und* Passwort, machen lassen, bevor man die prüft. Wenn man nämlich beim Namen den Benutzer schon wissen lässt ob man ihn kennt oder nicht, dann kann ein Angreifer den Namen und das Passwort getrennt raten. Wenn man beides zugleich prüft, sind auch die Namen schon besser gegen raten geschützt.

Wie man etwas wiederholt hat Jankie ja bereits gezeigt: Eine Schleife. Wenn man beim Schleifeneintritt nicht weiss wie oft die Schleife wiederholt werden wird und auch noch keinen Abbruchbedingung an der Stelle formulieren kann, dann nimmt man eine ”Endlosschleife” (``while True:``). Die kann man dann im Schleifenkörper mit der ``break``-Anweisung verlassen. Das machst Du im Grunde ja bereits für das Rechnen selbst. Dann musst es halt auch für die Aktivitäten machen.

Mit ”WebTigerJython” programmierst Du kein Python sondern eine Sprache die Python sehr ähnlich ist. Und die Turtle-Befehle dort sind auch nicht die gleichen wie die vom `turtle`-Modul aus der Python-Standardbibliothek. Warum TigerJython an der Stelle abweicht ist mir ein Rätsel. Die haben da dann auch Java-Namenskonventionen. Bäh.

Was soll die 4 bei `password4`? Man nummeriert in aller Regel keine Namen. Dann will man entweder bessere Namen oder gar keine Einzelnamen sondern eine Datenstruktur. Oft eine Liste.

Der Code der ausgeführt werden soll wenn der Benutzer die richtigen Zugangsdaten eingegeben hat, muss entweder dort stehen wo auch das ``print("Zugriff gewährt!")`` steht, oder man verschiebt den Code in eine Funktion und bricht die ab, falls falsche Zugangsdaten eingegeben wurden.

Man hat sowieso in der Regel immer eine Funktion, denn auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst und deren Ausführung durch ein ``if __name__ == "__main__":`` bedingt wird. Auch wenn das im Webeditor von TigerJython nicht so viel Sinn macht, funktioniert es dort, und man sollte sich das IMHO gleich angewöhnen.

Statt `activity` mit drei Werten zu vergleichen und das mit ``or`` zu Verknüpfen würde man eher den ``in``-Operator mit einer Sequenz mit den Werten für den Test verwenden.

Bei solchen Benutzereingaben bietet es sich an die in Kleinbuchstaben zu wandeln und mit Worten in Kleinbuchstaben zu vergleichen, damit der Benutzer es einfacher hat und nicht auf Gross-/Kleinschreibung achten muss.

Namen sollte man nicht kryptisch abkürzen. Wenn man `number` oder `operator` meint, sollte man das auch schreiben.

In den ``if``/``elif``-Zweigen steht fast überall das gleiche, es unterscheided sich nur der Operator und die Zeichenkette mit dem Operator bei der ersten Ausgabe. Die Zeichenkette kann man sich sparen weil `oper` ja bereits diesen Wert hat, womit das erste `print()` in jedem Fall gleich ist. Wenn man in den Zweigen nur das Ergebnis berechnet, dann kann man beide `print()`-Aufrufe *einmal* *hinter* das ganze ``if``-Konstrukt schreiben.

Zwischenstand:

Code: Alles auswählen

#!/usr/bin/env python3


def main():
    username = input("Bitte geben sie ihren Benutzernamen ein: ")
    password = input("Bitte gib dein Passwort ein, {}: ".format(username))
    if not (username == "Benutzer 1" and password == "passwort"):
        print("Falsche Zugangsdaten!")
        return

    print("Zugriff gewährt!")
    while True:
        activity = input("Was möchtest du jetzt machen? ").lower()
        if activity in ["tr", "rechnen", "taschenrechner"]:
            print("Okay, jetzt wird gerechnet!")
            while True:
                number_a = int(input("Gib die erste Zahl ein: "))
                operator = input(
                    "Welche Rechenoperation soll durchgeführt werden?"
                    " (+,-,/,*): "
                )
                number_b = int(input("Gib die zweite Zahl ein: "))
                #
                # TODO ``if``-Konstrukt durch Wörterbuch ersetzen, welches
                # Operator auf passende Funktion aus dem `operator`-Modul
                # abbildet.
                #
                if operator == "+":
                    result = number_a + number_b
                elif operator == "-":
                    result = number_a - number_b
                elif operator == "/":
                    result = number_a / number_b
                elif operator == "*":
                    result = number_a * number_b
                else:
                    result = None

                if result is None:
                    print("Deine Eingaben sind nicht gültig!")
                else:
                    print(
                        "Deine Rechnung: {} {} {}.".format(
                            number_a, operator, number_b
                        )
                    )
                    print("Ergebnis: {}.".format(result))

                jein = input(
                    "Willst du weiter rechnen, oder etwas anderes machen?"
                ).lower()
                if jein in ["nein", "stopp"]:
                    break


if __name__ == "__main__":
    main()
Die `main()`-Funktion macht hier aber viel zu viel, das sollte man dringend sinnvoll auf Funktionen aufteilen.

Und es fehlt Fehlerbehandlung. Wenn der Benutzer beispielsweise keine Zahlen eingibt, oder wenn er Division auswählt und als zweiten Operanden eine 0 eingibt.

PS:Oi, Du hast mein Avatar-Bild geklaut! 😠
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
GhastCraftHD
User
Beiträge: 6
Registriert: Freitag 20. März 2020, 07:54
Wohnort: Hamburg
Kontaktdaten:

@_blackjack_ nimms als Kompliment, es sieht halt einfach gut aus.

An die anderen:
Ich danke euch vielmals für eure tolle Hilfe.
Wir nehmen Python gerade in Informatik durch und deswegen bin ich noch nicht so erfahren.
Ich versuche zu eure guten Vorschläge zu verstehen und sie richtig anwenden zu können.
Auch vielen Dank an die Vielen Tipps.
DANKE!!!
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

GhastCraftHD hat geschrieben: Freitag 20. März 2020, 13:29 @_blackjack_ nimms als Kompliment, es sieht halt einfach gut aus.
Ich weiss nicht, ob wir hier eine offizielle Policy haben - aber ich wuerde mir wuenschen, du denkst dir was eigenes aus. Solange das nicht der Fall ist, werden ich jedenfalls auf keine deiner Fragen eingehen. Und wenn sich der betroffene __blackjack__ da noch mit anschliesst, dann hast du schon zusammen ~60% der Poweruser verloren. Ueberleg's dir.
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@GhastCraftHD: Das Kompliment nehme ich gerne an, das ist nämlich selbst gemacht. In einem C64-Emulator fix aus den Grafikzeichen zusammengetippt und dann einen Screenshot gemacht. 😎

Der Zweck von Avataren ist ja, dass man die Benutzer daran optisch leicht erkennen/unterscheiden kann. Du kannst das gerne als Grundlage nehmen und soweit verändern das man die beiden nicht verwechseln kann.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
hyle
User
Beiträge: 96
Registriert: Sonntag 22. Dezember 2019, 23:19
Wohnort: Leipzig

GhastCraftHD hat geschrieben: Freitag 20. März 2020, 13:29 nimms als Kompliment, es sieht halt einfach gut aus.
:shock: :roll: (SCNR!)
Alles was wir sind ist Sand im Wind Hoschi.
GhastCraftHD
User
Beiträge: 6
Registriert: Freitag 20. März 2020, 07:54
Wohnort: Hamburg
Kontaktdaten:

@_blackjack_

Sorry, is weg
GhastCraftHD
User
Beiträge: 6
Registriert: Freitag 20. März 2020, 07:54
Wohnort: Hamburg
Kontaktdaten:

Welches Python-Programm könntet ihr mir denn für Linux oder Raspian empfehlen?
Also zum Programmieren.
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@GhastCraftHD: Editoren und IDEs gibt's wie Sand am Meer. Da solltest Du selbst ein wenig forschen welches Programm am besten zu Dir passt. Ich persönlich verwende Sublime Text, der allerdings etwas kostet, und Vim wenn ich auf der Konsole arbeite, beispielsweise wenn ich über eine SSH-Verbindung direkt auf einem Server arbeiten muss.

Neben einem Editor habe ich immer noch eine interaktive Python-Shell offen, entweder IPython in der Konsole oder JupyterLab im Browser, zum herum probieren und erkunden von Bibliotheken.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Jankie: `print()` muss nicht zwingend auf die `main()`-Funktion beschränkt sein, aber `print()` und `input()` sind Benutzerinteraktion und die sollte man möglichst von der Programmlogik trennen, damit man die Programmlogik ohne einen Benutzer zu benötigen (automatisiert) testen und wiederverwenden kann. Also letztlich die gleiche Argumentation warum man GUI-Code und Programmlogik trennt, denn auch der GUI-Code sollte nur zur Kommunikation mit dem Benutzer dienen.

In dem Beispiel hier würde man beispielsweise sinnvollerweise eine Funktion schreiben die den Benutzer zur Eingabe einer Zahl auffordert, weil man diesen Vorgang zweimal benötigt, einmal für jeden Operanden, und weil das an sich auch eine in sich geschlossene Teilaufgabe darstellt. In dieser Funktion würde man natürlich `input()` und `print()` für eventuelle Fehlermeldungen verwenden.

Neben `print()` um direkt mit dem Benutzer zu kommunizieren, gibt es das noch um die Fehlersuche zu erleichtern oder in Programmlogik allgemein den Fortschritt auszugeben. Bei solchen `print()`-Aufrufen sollte man über Logging nachdenken. Dann kann man die Ausgaben anhand des Log-Levels auch leicht ein-/auschalten oder das ganze in eine oder mehrere Logdateien schreiben (lassen).
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Noch ein Ansatz das auf Funktionen aufzuteilen und mit Fehlerbehandlung (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python3
from operator import add, sub, truediv, mul

SYMBOL_TO_OPERATION = {"+": add, "-": sub, "/": truediv, "*": mul}


def check_credentials():
    username = input("Bitte geben Sie ihren Benutzernamen ein: ")
    password = input("Bitte geben Sie ihr Passwort ein, {}: ".format(username))
    return username == "Benutzer 1" and password == "passwort"


def ask_for_confirmation(prompt):
    return input(prompt).lower() not in ["n", "nein", "stopp"]


def ask_for_integer(prompt):
    prompt += ": "
    while True:
        try:
            return int(input(prompt))
        except ValueError:
            print("Fehler! Bitte eine ganze Zahl eingeben.")


def ask_for_operation():
    symbols = ",".join(SYMBOL_TO_OPERATION)
    while True:
        operator = input(
            "Welche Rechenoperation soll durchgeführt werden? ({}): ".format(
                symbols
            )
        )
        if operator not in SYMBOL_TO_OPERATION:
            print("Ungültiger Operator: {}".format(operator))
        else:
            return operator, SYMBOL_TO_OPERATION[operator]


def run_calculator():
    print("Okay, jetzt wird gerechnet!")
    while True:
        number_a = ask_for_integer("Gib die erste Zahl ein")
        operator, operation = ask_for_operation()
        number_b = ask_for_integer("Gib die zweite Zahl ein")

        print("Deine Rechnung: {} {} {}.".format(number_a, operator, number_b))
        try:
            result = operation(number_a, number_b)
        except ZeroDivisionError:
            print("Fehler! Versuch durch 0 zu teilen.")
        else:
            print("Ergebnis: {}.".format(result))

        if not ask_for_confirmation(
            "Willst du weiter rechnen, oder etwas anderes machen?"
        ):
            break


def run_main_menu():
    while True:
        answer = input("Was möchtest du jetzt machen? ").lower()
        if answer in ["tr", "rechnen", "taschenrechner"]:
            run_calculator()


def main():
    if check_credentials():
        print("Zugriff gewährt!")
        run_main_menu()
    else:
        print("Falsche Zugangsdaten!")


if __name__ == "__main__":
    main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten