Also, ich habe kürzlich mit etwas Ähnlichem herumgespielt und folgende Lösung entwickelt, die eine Möglichkeit verwendet, Eingaben abzulehnen, bevor sie überhaupt auf logische Weise überprüft werden.
read_single_keypress()
mit freundlicher Genehmigung von https://stackoverflow.com/a/6599441/4532996
def read_single_keypress() -> str:
"""Wartet auf einen einzelnen Tastendruck auf stdin.
-- von :: https://stackoverflow.com/a/6599441/4532996
"""
import termios, fcntl, sys, os
fd = sys.stdin.fileno()
# alten Zustand speichern
flags_save = fcntl.fcntl(fd, fcntl.F_GETFL)
attrs_save = termios.tcgetattr(fd)
# auf roh setzen - die Vorgehensweise stammt aus der termios(3) Manpage.
attrs = list(attrs_save) # gespeicherte Version kopieren, um zu aktualisieren
# 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)
# nicht-blockieren ausschalten
fcntl.fcntl(fd, fcntl.F_SETFL, flags_save & ~os.O_NONBLOCK)
# einen einzelnen Tastenanschlag lesen
try:
ret = sys.stdin.read(1) # gibt ein einzelnes Zeichen zurück
except KeyboardInterrupt:
ret = 0
finally:
# alten Zustand wiederherstellen
termios.tcsetattr(fd, termios.TCSAFLUSH, attrs_save)
fcntl.fcntl(fd, fcntl.F_SETFL, flags_save)
return ret
def until_not_multi(chars) -> str:
"""Liest stdin, bis !(chars) erreicht wird"""
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:
"""Ein praktisches Beispiel:
Prüfen, ob ein Benutzer nur anhand von Tastendrücken wählen kann"""
print("Kannst du wählen? Alter : ", end="")
x = int("0" + until_not_multi("0123456789"))
if not x:
print("\nEntschuldigung, das Alter kann nur aus Ziffern bestehen.")
return
print("Dein Alter ist", x, "\nDu kannst wählen!" if x >= 18 else "Entschuldigung! Du kannst nicht wählen")
_can_you_vote()
Du findest das komplette Modul hier.
Beispiel:
$ ./input_constrain.py
Kannst du wählen? Alter : a
Entschuldigung, das Alter kann nur aus Ziffern bestehen.
$ ./input_constrain.py
Kannst du wählen? Alter : 23
Dein Alter ist 23
Du kannst wählen!
$ _
Bitte beachte, dass die Natur dieser Implementierung stdin schließt, sobald etwas, das keine Ziffer ist, gelesen wird. Ich habe nicht nach a
enter gedrückt, aber nach den Zahlen musste ich das tun.
Du könntest dies mit der thismany()
Funktion im selben Modul kombinieren, um beispielsweise nur drei Ziffern zuzulassen.