python input - Den Benutzer zur Eingabe auffordern, bis er eine gültige Antwort gibt





user command (11)


Der einfachste Weg, dies zu erreichen, wäre, die input in eine while-Schleife zu stellen. Verwenden Sie continue wenn Sie schlechte Eingabe erhalten, und break aus der Schleife, wenn Sie zufrieden sind.

Wenn Ihre Eingabe eine Ausnahme auslösen könnte

Verwenden Sie try and catch, um festzustellen, wann der Benutzer Daten eingibt, die nicht analysiert werden können.

while True:
    try:
        # Note: Python 2.x users should use raw_input, the equivalent of 3.x's input
        age = int(input("Please enter your age: "))
    except ValueError:
        print("Sorry, I didn't understand that.")
        #better try again... Return to the start of the loop
        continue
    else:
        #age was successfully parsed!
        #we're ready to exit the loop.
        break
if age >= 18: 
    print("You are able to vote in the United States!")
else:
    print("You are not able to vote in the United States.")

Implementierung eigener Validierungsregeln

Wenn Sie Werte ablehnen möchten, die Python erfolgreich parsen kann, können Sie Ihre eigene Validierungslogik hinzufügen.

while True:
    data = input("Please enter a loud message (must be all caps): ")
    if not data.isupper():
        print("Sorry, your response was not loud enough.")
        continue
    else:
        #we're happy with the value given.
        #we're ready to exit the loop.
        break

while True:
    data = input("Pick an answer from A to D:")
    if data.lower() not in ('a', 'b', 'c', 'd'):
        print("Not an appropriate choice.")
    else:
        break

Kombinieren von Ausnahmebehandlung und benutzerdefinierter Validierung

Beide obigen Techniken können zu einer Schleife kombiniert werden.

while True:
    try:
        age = int(input("Please enter your age: "))
    except ValueError:
        print("Sorry, I didn't understand that.")
        continue

    if age < 0:
        print("Sorry, your response must not be negative.")
        continue
    else:
        #age was successfully parsed, and we're happy with its value.
        #we're ready to exit the loop.
        break
if age >= 18: 
    print("You are able to vote in the United States!")
else:
    print("You are not able to vote in the United States.")

Alles in einer Funktion einkapseln

Wenn Sie Ihren Benutzer nach vielen verschiedenen Werten fragen müssen, kann es nützlich sein, diesen Code in eine Funktion zu stellen, damit Sie ihn nicht jedes Mal neu eingeben müssen.

def get_non_negative_int(prompt):
    while True:
        try:
            value = int(input(prompt))
        except ValueError:
            print("Sorry, I didn't understand that.")
            continue

        if value < 0:
            print("Sorry, your response must not be negative.")
            continue
        else:
            break
    return value

age = get_non_negative_int("Please enter your age: ")
kids = get_non_negative_int("Please enter the number of children you have: ")
salary = get_non_negative_int("Please enter your yearly earnings, in dollars: ")

Alles zusammenfügen

Sie können diese Idee erweitern, um eine sehr allgemeine Eingabefunktion zu erstellen:

def sanitised_input(prompt, type_=None, min_=None, max_=None, range_=None):
    if min_ is not None and max_ is not None and max_ < min_:
        raise ValueError("min_ must be less than or equal to max_.")
    while True:
        ui = input(prompt)
        if type_ is not None:
            try:
                ui = type_(ui)
            except ValueError:
                print("Input type must be {0}.".format(type_.__name__))
                continue
        if max_ is not None and ui > max_:
            print("Input must be less than or equal to {0}.".format(max_))
        elif min_ is not None and ui < min_:
            print("Input must be greater than or equal to {0}.".format(min_))
        elif range_ is not None and ui not in range_:
            if isinstance(range_, range):
                template = "Input must be between {0.start} and {0.stop}."
                print(template.format(range_))
            else:
                template = "Input must be {0}."
                if len(range_) == 1:
                    print(template.format(*range_))
                else:
                    print(template.format(" or ".join((", ".join(map(str,
                                                                     range_[:-1])),
                                                       str(range_[-1])))))
        else:
            return ui

Mit Verwendung wie:

age = sanitised_input("Enter your age: ", int, 1, 101)
answer = sanitised_input("Enter your answer: ", str.lower, range_=('a', 'b', 'c', 'd'))

Häufige Fallstricke und warum Sie sie vermeiden sollten

Die redundante Verwendung von redundanten input

Diese Methode funktioniert, wird aber allgemein als schlechter Stil angesehen:

data = input("Please enter a loud message (must be all caps): ")
while not data.isupper():
    print("Sorry, your response was not loud enough.")
    data = input("Please enter a loud message (must be all caps): ")

Es könnte anfangs attraktiv aussehen, weil es kürzer ist als die while True Methode, aber es verstößt gegen das Prinzip der Sich-nicht-selbst-Wiederholung der Softwareentwicklung. Dies erhöht die Wahrscheinlichkeit von Fehlern in Ihrem System. Was ist, wenn Sie zu 2.7 raw_input möchten, indem Sie die input in raw_input , aber versehentlich nur die erste input oben ändern? Es ist ein SyntaxError nur darauf wartet, zu passieren.

Rekursion wird deinen Stack zerstören

Wenn Sie gerade etwas über Rekursion gelernt haben, könnten Sie versucht sein, es in get_non_negative_int damit Sie die while-Schleife get_non_negative_int können.

def get_non_negative_int(prompt):
    try:
        value = int(input(prompt))
    except ValueError:
        print("Sorry, I didn't understand that.")
        return get_non_negative_int(prompt)

    if value < 0:
        print("Sorry, your response must not be negative.")
        return get_non_negative_int(prompt)
    else:
        return value

Dies scheint die meiste Zeit gut zu funktionieren. Wenn der Benutzer jedoch häufig ungültige Daten eingibt, wird das Skript mit einem RuntimeError: maximum recursion depth exceeded . Du denkst vielleicht, "kein Idiot würde 1000 Fehler in Folge machen", aber du unterschätzt den Einfallsreichtum von Narren!

Ich schreibe ein Programm, das Eingaben vom Benutzer akzeptieren muss.

#note: Python 2.7 users should use `raw_input`, the equivalent of 3.X's `input`
age = int(input("Please enter your age: "))
if age >= 18: 
    print("You are able to vote in the United States!")
else:
    print("You are not able to vote in the United States.")

Dies funktioniert wie erwartet, wenn der Benutzer sinnvolle Daten eingibt.

C:\Python\Projects> canyouvote.py
Please enter your age: 23
You are able to vote in the United States!

Aber wenn sie einen Fehler machen, stürzt sie ab:

C:\Python\Projects> canyouvote.py
Please enter your age: dickety six
Traceback (most recent call last):
  File "canyouvote.py", line 1, in <module>
    age = int(input("Please enter your age: "))
ValueError: invalid literal for int() with base 10: 'dickety six'

Anstatt zu stürzen, möchte ich es versuchen, die Eingabe erneut zu bekommen. So was:

C:\Python\Projects> canyouvote.py
Please enter your age: dickety six
Sorry, I didn't understand that.
Please enter your age: 26
You are able to vote in the United States!

Wie kann ich das erreichen? Was wäre, wenn ich auch Werte wie -1 zurückweisen möchte, was ein gültiger int , aber in diesem Kontext sinnlos?




Obwohl die angenommene Antwort erstaunlich ist. Ich möchte auch einen schnellen Hack für dieses Problem teilen. (Dies kümmert sich auch um das negative Altersproblem.)

f=lambda age: (age.isdigit() and ((int(age)>=18  and "Can vote" ) or "Cannot vote")) or \
f(raw_input("invalid input. Try again\nPlease enter your age: "))
print f(raw_input("Please enter your age: "))

PS Dieser Code ist für Python 2.x und kann nach 3.x exportiert werden, indem die Funktionen raw_input und print geändert werden.




Verwenden Sie die "while" -Anweisung, bis der Benutzer einen wahren Wert eingibt und wenn der Eingabewert keine Zahl ist oder ein Nullwert ist, überspringen Sie ihn und versuchen Sie erneut zu fragen und so weiter. Im Beispiel habe ich versucht, wirklich deine Frage zu beantworten. Wenn wir annehmen, dass unser Alter zwischen 1 und 150 liegt, wird der Eingabewert akzeptiert, sonst ist es ein falscher Wert. Zum Beenden des Programms kann der Benutzer die 0-Taste verwenden und sie als einen Wert eingeben.

Hinweis: Lesen Sie die Kommentare oben im Code.

# If your input value is only a number then use "Value.isdigit() == False".
# If you need an input that is a text, you should remove "Value.isdigit() == False".
def Input(Message):
    Value = None
    while Value == None or Value.isdigit() == False:
        try:        
            Value = str(input(Message)).strip()
        except InputError:
            Value = None
    return Value

# Example:
age = 0
# If we suppose that our age is between 1 and 150 then input value accepted,
# else it's a wrong value.
while age <=0 or age >150:
    age = int(Input("Please enter your age: "))
    # For terminating program, the user can use 0 key and enter it as an a value.
    if age == 0:
        print("Terminating ...")
        exit(0)

if age >= 18 and age <=150: 
    print("You are able to vote in the United States!")
else:
    print("You are not able to vote in the United States.")



Probier diese:-

def takeInput(required):
  print 'ooo or OOO to exit'
  ans = raw_input('Enter: ')

  if not ans:
      print "You entered nothing...!"
      return takeInput(required) 

      ##  FOR Exit  ## 
  elif ans in ['ooo', 'OOO']:
    print "Closing instance."
    exit()

  else:
    if ans.isdigit():
      current = 'int'
    elif set('[[email protected]#$%^&*()_+{}":/\']+$').intersection(ans):
      current = 'other'
    elif isinstance(ans,basestring):
      current = 'str'        
    else:
      current = 'none'

  if required == current :
    return ans
  else:
    return takeInput(required)

## pass the value in which type you want [str/int/special character(as other )]
print "input: ", takeInput('str')



Warum würdest du eine while True und dann aus dieser Schleife ausbrechen, während du deine Anforderungen einfach in die while-Anweisung stellen kannst, da alles was du willst ist zu stoppen, sobald du das Alter hast?

age = None
while age is None:
    input_value = input("Please enter your age: ")
    try:
        # try and convert the string input to a number
        age = int(input_value)
    except ValueError:
        # tell the user off
        print("{input} is not a number, please enter a number only".format(input=input_value))
if age >= 18:
    print("You are able to vote in the United States!")
else:
    print("You are not able to vote in the United States.")

Dies würde zu folgendem führen:

Please enter your age: *potato*
potato is not a number, please enter a number only
Please enter your age: *5*
You are not able to vote in the United States.

dies wird funktionieren, da das Alter niemals einen Wert haben wird, der keinen Sinn ergibt und der Code der Logik Ihres "Geschäftsprozesses" folgt




So bearbeiten Sie Ihren Code und beheben den Fehler:

while True:
    try:
       age = int(input("Please enter your age: "))
       if age >= 18: 
           print("You are able to vote in the United States!")
           break
       else:
           print("You are not able to vote in the United States.")
           break
    except ValueError:
       print("Please enter a valid response")



Also habe ich in letzter Zeit mit etwas Ähnlichem herumgespielt, und ich habe die folgende Lösung gefunden, die eine Art von Input verwendet, die Junk abweist, bevor sie überhaupt auf logische Weise überprüft wird.

read_single_keypress() freundlicher Genehmigung https://.com/a/6599441/4532996

def read_single_keypress() -> str:
    """Waits for a single keypress on stdin.
    -- from :: https://.com/a/6599441/4532996
    """

    import termios, fcntl, sys, os
    fd = sys.stdin.fileno()
    # save old state
    flags_save = fcntl.fcntl(fd, fcntl.F_GETFL)
    attrs_save = termios.tcgetattr(fd)
    # make raw - the way to do this comes from the termios(3) man page.
    attrs = list(attrs_save) # copy the stored version to update
    # iflag
    attrs[0] &= ~(termios.IGNBRK | termios.BRKINT | termios.PARMRK
                  | termios.ISTRIP | termios.INLCR | termios. IGNCR
                  | termios.ICRNL | termios.IXON )
    # oflag
    attrs[1] &= ~termios.OPOST
    # cflag
    attrs[2] &= ~(termios.CSIZE | termios. PARENB)
    attrs[2] |= termios.CS8
    # lflag
    attrs[3] &= ~(termios.ECHONL | termios.ECHO | termios.ICANON
                  | termios.ISIG | termios.IEXTEN)
    termios.tcsetattr(fd, termios.TCSANOW, attrs)
    # turn off non-blocking
    fcntl.fcntl(fd, fcntl.F_SETFL, flags_save & ~os.O_NONBLOCK)
    # read a single keystroke
    try:
        ret = sys.stdin.read(1) # returns a single character
    except KeyboardInterrupt:
        ret = 0
    finally:
        # restore old state
        termios.tcsetattr(fd, termios.TCSAFLUSH, attrs_save)
        fcntl.fcntl(fd, fcntl.F_SETFL, flags_save)
    return ret

def until_not_multi(chars) -> str:
    """read stdin until !(chars)"""
    import sys
    chars = list(chars)
    y = ""
    sys.stdout.flush()
    while True:
        i = read_single_keypress()
        _ = sys.stdout.write(i)
        sys.stdout.flush()
        if i not in chars:
            break
        y += i
    return y

def _can_you_vote() -> str:
    """a practical example:
    test if a user can vote based purely on keypresses"""
    print("can you vote? age : ", end="")
    x = int("0" + until_not_multi("0123456789"))
    if not x:
        print("\nsorry, age can only consist of digits.")
        return
    print("your age is", x, "\nYou can vote!" if x >= 18 else "Sorry! you can't vote")

_can_you_vote()

Sie können das komplette Modul here .

Beispiel:

$ ./input_constrain.py
can you vote? age : a
sorry, age can only consist of digits.
$ ./input_constrain.py 
can you vote? age : 23<RETURN>
your age is 23
You can vote!
$ _

Beachten Sie, dass das Wesen dieser Implementierung darin besteht, dass sie stdin schließt, sobald etwas gelesen wird, das keine Ziffer ist. Ich habe nach a nicht Enter gedrückt, aber ich musste nach den Zahlen.

Sie könnten dies mit der Funktion thismany() im selben Modul zusammenführen, um beispielsweise drei Ziffern zuzulassen.




Sie können allgemeinere Logik schreiben, damit der Benutzer nur eine bestimmte Anzahl von Malen eingeben kann, da derselbe Anwendungsfall in vielen realen Anwendungen auftritt.

def getValidInt(iMaxAttemps = None):
  iCount = 0
  while True:
    # exit when maximum attempt limit has expired
    if iCount != None and iCount > iMaxAttemps:
       return 0     # return as default value

    i = raw_input("Enter no")
    try:
       i = int(i)
    except ValueError as e:
       print "Enter valid int value"
    else:
       break

    return i

age = getValidInt()
# do whatever you want to do.



def validate_age(age):
    if age >=0 :
        return True
    return False

while True:
    try:
        age = int(raw_input("Please enter your age:"))
        if validate_age(age): break
    except ValueError:
        print "Error: Invalid age."



Sie können die Eingabeanweisung eine Weile lang True Schleife machen, so dass sie wiederholt nach der Benutzereingabe fragt und diese Schleife dann bricht, wenn der Benutzer die Antwort eingibt, die Sie möchten. Und Sie können die Blöcke try und except verwenden, um ungültige Antworten zu verarbeiten.

while True:

    var = True

    try:
        age = int(input("Please enter your age: "))

    except ValueError:
        print("Invalid input.")
        var = False

    if var == True:
        if age >= 18:
                print("You are able to vote in the United States.")
                break
        else:
            print("You are not able to vote in the United States.")

Die var-Variable ist nur so, dass, wenn der Benutzer eine Zeichenfolge anstelle einer ganzen Zahl eingibt, das Programm nicht zurückgibt "Sie können nicht in den Vereinigten Staaten wählen".




Nein. Sie können Daten nicht generisch filtern, ohne dafür einen Kontext zu haben. Manchmal möchten Sie eine SQL-Abfrage als Eingabe verwenden und manchmal möchten Sie HTML als Eingabe verwenden.

Sie müssen die Eingabe auf einer Whitelist filtern - stellen Sie sicher, dass die Daten mit den Spezifikationen übereinstimmen, die Sie erwarten. Dann müssen Sie es, bevor Sie es verwenden, es zu entkommen, abhängig von dem Kontext, in dem Sie es verwenden.

Der Prozess des Entweichens von Daten für SQL - um SQL-Injection zu verhindern - unterscheidet sich erheblich von dem Prozess des Entweichens von Daten für (X) HTML, um XSS zu verhindern.





python validation loops python-3.x user-input