APT命令行界面式的yes/no输入?

有没有什么简单的方法来实现APT (高级打包工具)命令行界面在Python中的作用?

我的意思是,当包管理器提示一个是/否的问题后跟[Yes/no]时,脚本接受YES/Y/yes/y输入(默认为Yes,由大写字母暗示)。

我在官方文档中唯一找到的东西是inputraw_input

我知道模仿它并不难,但是重写:|很烦人

234420 次浏览

正如你提到的,最简单的方法是使用raw_input()(或简单地用input()代替Python 3)。没有内置的方法可以做到这一点。从577058年食谱:

import sys




def query_yes_no(question, default="yes"):
"""Ask a yes/no question via raw_input() and return their answer.


"question" is a string that is presented to the user.
"default" is the presumed answer if the user just hits <Enter>.
It must be "yes" (the default), "no" or None (meaning
an answer is required of the user).


The "answer" return value is True for "yes" or False for "no".
"""
valid = {"yes": True, "y": True, "ye": True, "no": False, "n": False}
if default is None:
prompt = " [y/n] "
elif default == "yes":
prompt = " [Y/n] "
elif default == "no":
prompt = " [y/N] "
else:
raise ValueError("invalid default answer: '%s'" % default)


while True:
sys.stdout.write(question + prompt)
choice = input().lower()
if default is not None and choice == "":
return valid[default]
elif choice in valid:
return valid[choice]
else:
sys.stdout.write("Please respond with 'yes' or 'no' " "(or 'y' or 'n').\n")

(对于Python 2,使用raw_input而不是input。) 使用例子:< / p >

>>> query_yes_no("Is cabbage yummier than cauliflower?")
Is cabbage yummier than cauliflower? [Y/n] oops
Please respond with 'yes' or 'no' (or 'y' or 'n').
Is cabbage yummier than cauliflower? [Y/n] [ENTER]
>>> True


>>> query_yes_no("Is cabbage yummier than cauliflower?", None)
Is cabbage yummier than cauliflower? [y/n] [ENTER]
Please respond with 'yes' or 'no' (or 'y' or 'n').
Is cabbage yummier than cauliflower? [y/n] y
>>> True

我会这样做:

# raw_input returns the empty string for "enter"
yes = {'yes','y', 'ye', ''}
no = {'no','n'}


choice = raw_input().lower()
if choice in yes:
return True
elif choice in no:
return False
else:
sys.stdout.write("Please respond with 'yes' or 'no'")

一个非常简单(但不是很复杂)的方法是:

msg = 'Shall I?'
shall = input("%s (y/N) " % msg).lower() == 'y'

你也可以写一个简单的(稍微改进的)函数:

def yn_choice(message, default='y'):
choices = 'Y/n' if default.lower() in ('y', 'yes') else 'y/N'
choice = input("%s (%s) " % (message, choices))
values = ('y', 'yes', '') if choices == 'Y/n' else ('y', 'yes')
return choice.strip().lower() in values

注意:在Python 2中,使用raw_input而不是input

在Python的标准库中有一个函数strtobool: http://docs.python.org/2/distutils/apiref.html?highlight=distutils.util#distutils.util.strtobool

你可以使用它来检查用户的输入并将其转换为TrueFalse值。

这个怎么样:

def yes(prompt = 'Please enter Yes/No: '):
while True:
try:
i = raw_input(prompt)
except KeyboardInterrupt:
return False
if i.lower() in ('yes','y'): return True
elif i.lower() in ('no','n'): return False

你可以尝试下面的代码来处理变量'accepted'中的选项:

print( 'accepted: {}'.format(accepted) )
# accepted: {'yes': ['', 'Yes', 'yes', 'YES', 'y', 'Y'], 'no': ['No', 'no', 'NO', 'n', 'N']}

这是密码。

#!/usr/bin/python3


def makeChoi(yeh, neh):
accept = {}
# for w in words:
accept['yes'] = [ '', yeh, yeh.lower(), yeh.upper(), yeh.lower()[0], yeh.upper()[0] ]
accept['no'] = [ neh, neh.lower(), neh.upper(), neh.lower()[0], neh.upper()[0] ]
return accept


accepted = makeChoi('Yes', 'No')


def doYeh():
print('Yeh! Let\'s do it.')


def doNeh():
print('Neh! Let\'s not do it.')


choi = None
while not choi:
choi = input( 'Please choose: Y/n? ' )
if choi in accepted['yes']:
choi = True
doYeh()
elif choi in accepted['no']:
choi = True
doNeh()
else:
print('Your choice was "{}". Please use an accepted input value ..'.format(choi))
print( accepted )
choi = None

正如@Alexander Artemenko提到的,这里有一个使用strtoool的简单解决方案

from distutils.util import strtobool


def user_yes_no_query(question):
sys.stdout.write('%s [y/n]\n' % question)
while True:
try:
return strtobool(raw_input().lower())
except ValueError:
sys.stdout.write('Please respond with \'y\' or \'n\'.\n')


#usage


>>> user_yes_no_query('Do you like cheese?')
Do you like cheese? [y/n]
Only on tuesdays
Please respond with 'y' or 'n'.
ok
Please respond with 'y' or 'n'.
y
>>> True

我知道这已经被回答了很多方法,这可能不能回答OP的具体问题(标准列表),但这是我为最常见的用例所做的,它比其他回答简单得多:

answer = input('Please indicate approval: [y/n]')
if not answer or answer[0].lower() != 'y':
print('You did not indicate approval')
exit(1)

这是我所使用的:

import sys


# cs = case sensitive
# ys = whatever you want to be "yes" - string or tuple of strings


#  prompt('promptString') == 1:               # only y
#  prompt('promptString',cs = 0) == 1:        # y or Y
#  prompt('promptString','Yes') == 1:         # only Yes
#  prompt('promptString',('y','yes')) == 1:   # only y or yes
#  prompt('promptString',('Y','Yes')) == 1:   # only Y or Yes
#  prompt('promptString',('y','yes'),0) == 1: # Yes, YES, yes, y, Y etc.


def prompt(ps,ys='y',cs=1):
sys.stdout.write(ps)
ii = raw_input()
if cs == 0:
ii = ii.lower()
if type(ys) == tuple:
for accept in ys:
if cs == 0:
accept = accept.lower()
if ii == accept:
return True
else:
if ii == ys:
return True
return False

你也可以使用提词员

无耻地从README中截取:

#pip install prompter


from prompter import yesno


>>> yesno('Really?')
Really? [Y/n]
True


>>> yesno('Really?')
Really? [Y/n] no
False


>>> yesno('Really?', default='no')
Really? [y/N]
True
def question(question, answers):
acceptable = False
while not acceptable:
print(question + "specify '%s' or '%s'") % answers
answer = raw_input()
if answer.lower() == answers[0].lower() or answers[0].lower():
print('Answer == %s') % answer
acceptable = True
return answer


raining = question("Is it raining today?", ("Y", "N"))

换做是我就会这么做。

输出

Is it raining today? Specify 'Y' or 'N'
> Y
answer = 'Y'

我修改了fmark的答案,用python 2/3兼容更pythonic。

如果你对更多错误处理感兴趣,请参阅Ipython的实用模块

# PY2/3 compatibility
from __future__ import print_function
# You could use the six package for this
try:
input_ = raw_input
except NameError:
input_ = input


def query_yes_no(question, default=True):
"""Ask a yes/no question via standard input and return the answer.


If invalid input is given, the user will be asked until
they acutally give valid input.


Args:
question(str):
A question that is presented to the user.
default(bool|None):
The default value when enter is pressed with no value.
When None, there is no default value and the query
will loop.
Returns:
A bool indicating whether user has entered yes or no.


Side Effects:
Blocks program execution until valid input(y/n) is given.
"""
yes_list = ["yes", "y"]
no_list = ["no", "n"]


default_dict = {  # default => prompt default string
None: "[y/n]",
True: "[Y/n]",
False: "[y/N]",
}


default_str = default_dict[default]
prompt_str = "%s %s " % (question, default_str)


while True:
choice = input_(prompt_str).lower()


if not choice and default is not None:
return default
if choice in yes_list:
return True
if choice in no_list:
return False


notification_str = "Please respond with 'y' or 'n'"
print(notification_str)

这是我对它的看法,我只是想中止如果用户没有确认的行动。

import distutils


if unsafe_case:
print('Proceed with potentially unsafe thing? [y/n]')
while True:
try:
verify = distutils.util.strtobool(raw_input())
if not verify:
raise SystemExit  # Abort on user reject
break
except ValueError as err:
print('Please enter \'yes\' or \'no\'')
# Try again
print('Continuing ...')
do_unsafe_thing()

在2.7中,这是不是太非python化了?

if raw_input('your prompt').lower()[0]=='y':
your code here
else:
alternate code here

它至少能捕捉到“是”的任何变化。

对python 3执行同样的操作。x,其中raw_input()不存在:

def ask(question, default = None):
hasDefault = default is not None
prompt = (question
+ " [" + ["y", "Y"][hasDefault and default] + "/"
+ ["n", "N"][hasDefault and not default] + "] ")


while True:
sys.stdout.write(prompt)
choice = input().strip().lower()
if choice == '':
if default is not None:
return default
else:
if "yes".startswith(choice):
return True
if "no".startswith(choice):
return False


sys.stdout.write("Please respond with 'yes' or 'no' "
"(or 'y' or 'n').\n")

你可以使用点击confirm方法。

import click


if click.confirm('Do you want to continue?', default=True):
print('Do something')

这将打印:

$ Do you want to continue? [Y/n]:

应该适用于Linux, Mac或Windows上的Python 2/3

文档:http://click.pocoo.org/5/prompts/#confirmation-prompts

对于Python 3,我使用这个函数:

def user_prompt(question: str) -> bool:
""" Prompt the yes/no-*question* to the user. """
from distutils.util import strtobool


while True:
user_input = input(question + " [y/n]: ")
try:
return bool(strtobool(user_input))
except ValueError:
print("Please use y/n or yes/no.\n")

strtobool()函数的作用是:将字符串转换为bool类型。如果字符串不能被解析,它将引发ValueError。

在Python 3中,raw_input()已被重命名为input()

正如Geoff所说,strtoool实际上返回0或1,因此结果必须转换为bool类型。


这是strtobool的实现,如果你想让特殊的词被识别为true,你可以复制代码并添加你自己的大小写。

def strtobool (val):
"""Convert a string representation of truth to true (1) or false (0).
True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
are 'n', 'no', 'f', 'false', 'off', and '0'.  Raises ValueError if
'val' is anything else.
"""
val = val.lower()
if val in ('y', 'yes', 't', 'true', 'on', '1'):
return 1
elif val in ('n', 'no', 'f', 'false', 'off', '0'):
return 0
else:
raise ValueError("invalid truth value %r" % (val,))

作为一个编程新手,我发现上面的一堆答案过于复杂,特别是如果目标是有一个简单的函数,你可以传递各种是/否问题,迫使用户选择是或否。在浏览了这篇文章和其他几篇文章,并借鉴了各种各样的好想法后,我得出了以下结论:

def yes_no(question_to_be_answered):
while True:
choice = input(question_to_be_answered).lower()
if choice[:1] == 'y':
return True
elif choice[:1] == 'n':
return False
else:
print("Please respond with 'Yes' or 'No'\n")


#See it in Practice below


musical_taste = yes_no('Do you like Pine Coladas?')
if musical_taste == True:
print('and getting caught in the rain')
elif musical_taste == False:
print('You clearly have no taste in music')

Python 3.8及以上版本的一行代码:

while res:= input("When correct, press enter to continue...").lower() not in {'y','yes','Y','YES',''}: pass

Python x.x

res = True
while res:
res = input("Please confirm with y/yes...").lower(); res = res not in {'y','yes','Y','YES',''}

由于答案预期是或否,在下面的例子中,第一个解决方案是使用while函数重复这个问题,第二个解决方案是使用recursion -是定义事物本身的过程。

def yes_or_no(question):
while "the answer is invalid":
reply = str(input(question+' (y/n): ')).lower().strip()
if reply[:1] == 'y':
return True
if reply[:1] == 'n':
return False


yes_or_no("Do you know who Novak Djokovic is?")

第二个解决方案:

def yes_or_no(question):
"""Simple Yes/No Function."""
prompt = f'{question} ? (y/n): '
answer = input(prompt).strip().lower()
if answer not in ['y', 'n']:
print(f'{answer} is invalid, please try again...')
return yes_or_no(question)
if answer == 'y':
return True
return False


def main():
"""Run main function."""
answer = yes_or_no("Do you know who Novak Djokovic is?")
print(f'you answer was: {answer}')




if __name__ == '__main__':
main()

我过去常做的是……

question = 'Will the apple fall?'
print(question)
answer = int(input("Pls enter the answer: "
if answer == "y",
print('Well done')
print(answer)