Input sì / no simile all'interfaccia della riga di comando APT?


169

Esiste un modo breve per ottenere ciò che fa l'interfaccia della riga di comando APT ( Advanced Package Tool ) in Python?

Voglio dire, quando il gestore pacchetti richiede una domanda sì / no seguita da [Yes/no], lo script accetta YES/Y/yes/yo Enter(il valore predefinito è Yescome suggerito dalla lettera maiuscola).

L'unica cosa che trovo nei documenti ufficiali è inpute raw_input...

So che non è così difficile da emulare, ma è fastidioso riscrivere: |


15
In Python 3, raw_input()viene chiamato input().
Tobu,

Risposte:


222

Come hai già detto, il modo più semplice è usare raw_input()(o semplicemente input()per Python 3 ). Non esiste un modo integrato per farlo. Dalla ricetta 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 = raw_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")

Esempio di utilizzo:

>>> 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

elif choice in valid:E probabilmente restituirei un booleano.
Ignacio Vazquez-Abrams,

Buona scelta Ignacio, che modifica
segna il

24
In realtà, esiste una funzione strtobool nella libreria standard: docs.python.org/2/distutils/…
Alexander Artemenko,

14
Solo un ricordo: raw_input()si chiama input()in Python3
nachouve il

Davvero super utile! Basta sostituire raw_input()con input()per Python3.
Muhammad Haseeb,

93

Lo farei così:

# 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'")

8
raw_input()viene chiamato input()in Python3
gizzmole il

49

C'è una funzione strtoboolnella libreria standard di Python: http://docs.python.org/2/distutils/apiref.html?highlight=distutils.util#distutils.util.strtobool

Puoi usarlo per controllare l'input dell'utente e trasformarlo in Trueo Falsevalore.


fprobabilmente sta per False, e False == 0quindi ottengo la logica. Perché la funzione restituisca an intinvece di a boolè un mistero per me.
François Leblanc,

@ FrançoisLeblanc su Perché è più comune nei database. Se non è esplicitamente Falseo 0(Zero). Qualsiasi cosa, altra cosa che viene valutata utilizzando la funzione bool diventa vero e tornerà: 1.
JayRizzo,

@JayRizzo L'ho capito, e sono entrambi funzionalmente simili sotto molti aspetti. Ma significa che non puoi usare il confronto singleton, cioè if strtobool(string) is False: do_stuff().
François Leblanc,

48

Un modo molto semplice (ma non molto sofisticato) di farlo per una sola scelta sarebbe:

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

Puoi anche scrivere una semplice funzione (leggermente migliorata) attorno a questo:

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

Nota: su Python 2, utilizzare raw_inputinvece di input.


7
Adoro il primo approccio. Breve e facile Ho usato qualcosa del tiporesult = raw_input("message").lower() in ('y','yes')
Adrian Shum


24

come accennato da @ Alexander Artemenko, ecco una soluzione semplice che utilizza strtobool

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

8
solo curioso ... perché sys.stdout.writeinvece di print?
Anentropico

2
Nota che strtobool()(dai miei test) non richiede a lower(). Questo non è esplicito nella sua documentazione, tuttavia.
Michael - Dov'è Clay Shirky il

15

So che è stato risposto in diversi modi e questo potrebbe non rispondere alla domanda specifica di OP (con l'elenco dei criteri), ma questo è quello che ho fatto per il caso d'uso più comune ed è molto più semplice delle altre risposte:

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

questo non funziona con Python 2 - è raw_inputstato rinominato inputin Python 3 stackoverflow.com/questions/21122540/…
Brian Tingle

9

Puoi anche usare il prompt .

Spudoratamente tratto dal 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

4
Fai attenzione che il comportamento del suggeritore è piuttosto arretrato quando lo usi con "default = 'no'"; restituirà True quando scegli "no" e False quando scegli "sì".
rem

7

Ho modificato la risposta di Fmark con Python 2/3 compatibile più Pythonic.

Vedi il modulo di utilità di ipython se sei interessato a qualcosa con più gestione degli errori

# 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)

Compatibile con Python 2 e 3, molto leggibile. Ho finito per usare questa risposta.
François Leblanc,

4

2.7, è troppo non pitonico?

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

cattura almeno qualsiasi variazione di Sì.


4

Fare lo stesso con Python 3.x, dove raw_input()non esiste:

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")

No, questo non funziona. In più di un modo in realtà. Attualmente sto cercando di risolverlo, ma penso che dopo aver finito, sembrerà molto simile alla risposta accettata.
Gormador,

Ti ho modificato anwser @pjm. Per favore, considera di esaminarlo :-)
Gormador

3

Per Python 3, sto usando questa funzione:

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]: ").lower()
        try:
            result = strtobool(user_input)
            return result
        except ValueError:
            print("Please use y/n or yes/no.\n")

Lo strtobool funzione converte una stringa in un bool. Se la stringa non può essere analizzata genererà un ValueError.

In Python 3 raw_input è stato rinominato in input .


2

Puoi provare qualcosa come il codice qui sotto per essere in grado di lavorare con le scelte della variabile 'accettato' mostra qui:

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

Ecco il codice ..

#!/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

2

Come noob di programmazione, ho trovato un sacco di risposte sopra eccessivamente complesse, soprattutto se l'obiettivo è avere una semplice funzione a cui è possibile passare varie domande sì / no, costringendo l'utente a selezionare sì o no. Dopo aver setacciato questa pagina e molte altre, e preso in prestito tutte le varie buone idee, ho finito con il seguente:

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')

1
L'argomento non dovrebbe essere chiamato "domanda" anziché "risposta"?
AFP_555,

1

Cosa ne pensi di questo:

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

1

Questo è quello che uso:

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

1
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"))

È così che lo farei.

Produzione

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

1

Ecco la mia opinione su di esso, volevo semplicemente interrompere se l'utente non ha confermato l'azione.

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()

0

Un esempio di Python 3 ripulito:

# inputExample.py

def confirm_input(question, default="no"):
    """Ask a yes/no question 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", "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: '{}}'".format(default))

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

def main():

    if confirm_input("\nDo you want to continue? "):
        print("You said yes because the function equals true. Continuing.")
    else:
        print("Quitting because the function equals false.")

if __name__ == "__main__":
    main()
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.