Python 请求用户输入,直到他们给出有效响应
我正在编写一个接受用户输入的程序Python 请求用户输入,直到他们给出有效响应,python,Python,我正在编写一个接受用户输入的程序 #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 t
#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.")
只要用户输入有意义的数据,程序就会按预期工作
C:\Python\Projects>canyouvote.py
请输入您的年龄:23岁
你可以在美国投票!
但如果用户输入无效数据,则会失败:
C:\Python\Projects>canyouvote.py
请输入您的年龄:dickety六岁
回溯(最近一次呼叫最后一次):
文件“canyouvote.py”,第1行,在
年龄=整数(输入(“请输入您的年龄:”)
ValueError:基数为10的int()的文本无效:“dickety六”
我希望程序再次请求输入,而不是崩溃。像这样:
C:\Python\Projects>canyouvote.py
请输入您的年龄:dickety六岁
对不起,我不明白。
请输入您的年龄:26岁
你可以在美国投票!
当输入非感官数据时,如何使程序请求有效输入而不是崩溃
如何拒绝像
-1
这样的值,这是一个有效的int
,但在这种情况下毫无意义?实现这一点的最简单方法是将输入
方法置于while循环中。当您得到错误的输入时使用,当您满意时,将从循环中断开
当您的输入可能引发异常时
用于检测用户何时输入无法解析的数据
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.")
实现您自己的验证规则
如果要拒绝Python可以成功解析的值,可以添加自己的验证逻辑
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
结合异常处理和自定义验证
上述两种技术可以组合成一个循环
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.")
常见的陷阱,以及您应该避免它们的原因
冗余输入
语句的冗余使用
这种方法可行,但通常被认为是拙劣的风格:
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): ")
一开始它可能看起来很吸引人,因为它比while True
方法短,但它违反了软件开发的原则。这会增加系统中出现错误的可能性。如果您想通过将input
更改为raw\u input
,而意外地只更改上面的第一个input
,将后端口转换为2.7,该怎么办?这是一个正在等待发生的语法错误
递归会毁掉你的堆栈
如果您刚刚了解了递归,您可能会在get\u non\u negative\u int
中使用它,这样您就可以处理while循环了
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
def get_non_negative_int(提示):
尝试:
值=int(输入(提示))
除值错误外:
打印(“对不起,我不明白。”)
返回获取非负整数(提示)
如果值<0:
打印(“对不起,您的回答不能是否定的。”)
返回获取非负整数(提示)
其他:
返回值
这在大多数情况下似乎工作正常,但如果用户输入无效数据的次数足够多,脚本将以运行时错误终止:超过最大递归深度。你可能认为“没有傻瓜会连续犯1000个错误”,但你低估了傻瓜的创造力 尽管公认的答案令人惊讶。我还想分享一下这个问题的快速解决方法。(这也解决了消极的年龄问题。)
另外,这段代码是为Python3.x编写的。为什么要执行while True
,然后打破这个循环,而您也可以将您的需求放在while语句中,因为您只想在达到年龄后停止
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.")
这将导致以下情况:
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.
这将起作用,因为年龄永远不会有一个没有意义的值,代码遵循“业务流程”的逻辑。因此,我最近在处理类似的问题,我提出了以下解决方案,它使用一种获取输入的方式,拒绝垃圾,在以任何逻辑方式检查之前
read\u single\u keypress()
您可以找到完整的模块
例如:
$ ./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!
$ _
$。/input\u constraint.py
你能投票吗?年龄:a
对不起,年龄只能由数字组成。
$./input\u constraint.py
你能投票吗?年龄:23
你的年龄是23岁
你可以投票!
$ _
请注意,此实现的本质是,一旦读取非数字的内容,它就会关闭stdin。我没有在a
之后按enter键,但我需要在数字之后按enter键
您可以将其与同一模块中的thismany()
函数合并,以仅允许(比如)三位数字。当尝试/时,除了块将起作用,完成此任务的更快更干净的方法是使用str.isdigit()
您可以编写更通用的逻辑,允许用户只输入特定的次数,因为在许多实际应用程序中都会出现相同的用例
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 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('[~!@#$%^&*()_+{}":/\']+$').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')
使用“while”语句,直到用户输入一个真值,如果输入值不是一个数字或是一个空值,则跳过它并尝试再次询问,以此类推。
在这个例子中,我试图真实地回答你的问题。如果我们假设我们的年龄在1到150之间,那么输入值被接受,否则它是一个错误的值。
对于终止程序,用户可以使用0键并将其作为值输入
注意:阅读代码顶部的注释
#如果输入值只是一个数字,则使用“value.isdigit()==False”。
#如果需要文本输入,则应删除“Value.isdigit()==False”。
def输入(消息):
值=无
当Value==None或Value.isdigit()==False时:
尝试:
Value=str(输入(消息)).strip()
除输入者外:
值=无
返回值
#例如:
年龄=0
#如果我们假设我们的年龄在1到150岁之间,那么输入值可以接受,
#否则它是一个错误的值。
150岁时:
年龄=整数(输入(“请输入您的年龄:”)
#对于终止程序,用户可以使用0键并输入它
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.
def read_single_keypress() -> str:
"""Waits for a single keypress on stdin.
-- from :: https://stackoverflow.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()
$ ./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!
$ _
while True:
age = input("Please enter your age: ")
if age.isdigit():
age = int(age)
break
else:
print("Invalid number '{age}'. Try again.".format(age=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.")
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."
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 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('[~!@#$%^&*()_+{}":/\']+$').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')
# 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.")
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.")
class ValidationError(ValueError):
"""Special validation error - its message is supposed to be printed"""
pass
def RangeValidator(text,num,r):
"""Generic validator - raises 'text' as ValidationError if 'num' not in range 'r'."""
if num in r:
return num
raise ValidationError(text)
def ValidCol(c):
"""Specialized column validator providing text and range."""
return RangeValidator("Columns must be in the range of 0 to 3 (inclusive)",
c, range(4))
def ValidRow(r):
"""Specialized row validator providing text and range."""
return RangeValidator("Rows must be in the range of 5 to 15(exclusive)",
r, range(5,15))
def GetInt(text, validator=None):
"""Aks user for integer input until a valid integer is given. If provided,
a 'validator' function takes the integer and either raises a
ValidationError to be printed or returns the valid number.
Non integers display a simple error message."""
print()
while True:
n = input(text)
try:
n = int(n)
return n if validator is None else validator(n)
except ValueError as ve:
# prints ValidationErrors directly - else generic message:
if isinstance(ve, ValidationError):
print(ve)
else:
print("Invalid input: ", n)
column = GetInt("Pleased enter column: ", ValidCol)
row = GetInt("Pleased enter row: ", ValidRow)
print( row, column)
Pleased enter column: 22
Columns must be in the range of 0 to 3 (inclusive)
Pleased enter column: -2
Columns must be in the range of 0 to 3 (inclusive)
Pleased enter column: 2
Pleased enter row: a
Invalid input: a
Pleased enter row: 72
Rows must be in the range of 5 to 15(exclusive)
Pleased enter row: 9
9, 2
# Assuming Python3
import sys
class ValidationError(ValueError): # thanks Patrick Artner
pass
def validate_input(prompt, cast=str, cond=(lambda x: True), onerror=None):
if onerror==None: onerror = {}
while True:
try:
data = cast(input(prompt))
if not cond(data): raise ValidationError
return data
except tuple(onerror.keys()) as e: # thanks Daniel Q
print(onerror[type(e)], file=sys.stderr)
# No validation, equivalent to simple input:
anystr = validate_input("Enter any string: ")
# Get a string containing only letters:
letters = validate_input("Enter letters: ",
cond=str.isalpha,
onerror={ValidationError: "Only letters, please!"})
# Get a float in [0, 100]:
percentage = validate_input("Percentage? ",
cast=float, cond=lambda x: 0.0<=x<=100.0,
onerror={ValidationError: "Must be between 0 and 100!",
ValueError: "Not a number!"})
age = validate_input("Please enter your age: ",
cast=int, cond=lambda a:0<=a<150,
onerror={ValidationError: "Enter a plausible age, please!",
ValueError: "Enter an integer, please!"})
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.")
from ast import literal_eval
''' This function is used to identify the data type of input data.'''
def input_type(input_data):
try:
return type(literal_eval(input_data))
except (ValueError, SyntaxError):
return str
flag = True
while(flag):
age = raw_input("Please enter your age: ")
if input_type(age)==float or input_type(age)==int:
if eval(age)>=18:
print("You are able to vote in the United States!")
flag = False
elif eval(age)>0 and eval(age)<18:
print("You are not able to vote in the United States.")
flag = False
else: print("Please enter a valid number as your age.")
else: print("Sorry, I didn't understand that.")
def askName():
return input("Write your name: ").strip() or askName()
name = askName()
def askAge():
try: return int(input("Enter your age: "))
except ValueError: return askAge()
age = askAge()
def askAge():
try: return int(input("Enter your age: "))
except ValueError: return askAge()
age = askAge()
responseAge = [
"You are able to vote in the United States!",
"You are not able to vote in the United States.",
][int(age < 18)]
print(responseAge)
import click
number = click.prompt('Please enter a number', type=float)
print(number)
age = click.prompt("What's your age?", type=click.IntRange(1, 120))
print(age)
age = click.prompt("What's your age?", type=click.IntRange(min=14))
print(age)
choices = {'apple', 'orange', 'peach'}
choice = click.prompt('Provide a fruit', type=click.Choice(choices, case_sensitive=False))
print(choice)
path = click.prompt('Provide path', type=click.Path(exists=True, resolve_path=True))
print(path)
file = click.prompt('In which file to write data?', type=click.File('w'))
with file.open():
file.write('Hello!')
# More info about `lazy=True` at:
# https://click.palletsprojects.com/en/7.x/arguments/#file-opening-safety
file = click.prompt('Which file you wanna read?', type=click.File(lazy=True))
with file.open():
print(file.read())
password = click.prompt('Enter password', hide_input=True, confirmation_prompt=True)
print(password)
number = click.prompt('Please enter a number', type=int, default=42)
print(number)
while True:
age = int(input("Please enter your age: "))
if (age<=0) or (age>120):
print('Sorry, I did not understand that.Please try again')
continue
else:
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.")
break
while True:
try:
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.")
except Exception as e:
print("please enter number")
def ask():
answer = input("Please enter amount to convert: ")
if not answer.isdigit():
print("Invalid")
return ask()
Gbp = int(answer)
ask()
while True:
answer = input("Please enter amount to convert: ")
if not answer.isdigit():
print("Invalid")
continue
Gbp = int(answer)