APT Kommandozeilenschnittstelle-ähnliche Ja / Nein-Eingabe?

169

Gibt es einen kurzen Weg, um die Funktionen der APT- Befehlszeilenschnittstelle ( Advanced Package Tool ) in Python zu erreichen?

Ich meine, wenn der Paketmanager eine Ja / Nein-Frage gefolgt von gefolgt hat [Yes/no], akzeptiert das Skript YES/Y/yes/yoder Enter(standardmäßig Yeswie durch den Großbuchstaben angedeutet).

Das einzige, was ich in den offiziellen Dokumenten finde, ist inputund raw_input...

Ich weiß, es ist nicht so schwer zu emulieren, aber es ist ärgerlich, Folgendes umzuschreiben: |

h3.
quelle
15
In Python 3 raw_input()heißt input().
Tobu

Antworten:

222

Wie Sie bereits erwähnt haben, ist die Verwendung raw_input()(oder einfach input()für Python 3 ) am einfachsten . Es gibt keine eingebaute Möglichkeit, dies zu tun. Aus Rezept 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")

Anwendungsbeispiel:

>>> 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
fmark
quelle
elif choice in valid:Und ich würde wahrscheinlich einen Booleschen Wert zurückgeben.
Ignacio Vazquez-Abrams
Gute Wahl Ignacio, Änderung
fmark
24
Tatsächlich gibt es eine Funktion strtobool in der Standardbibliothek
Alexander Artemenko
14
Nur eine Erinnerung: raw_input()wird input()in Python3 aufgerufen
nachouve
In der Tat super hilfreich! Ersetzen Sie einfach raw_input()mit input()für Python3.
Muhammad Haseeb
93

Ich würde es so machen:

# 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'")
Vicki Laidler
quelle
8
raw_input()wird input()in Python3
Gizzmole
49

strtoboolIn der Standardbibliothek von Python gibt es eine Funktion : http://docs.python.org/2/distutils/apiref.html?highlight=distutils.util#distutils.util.strtobool

Sie können es verwenden, um Benutzereingaben zu überprüfen und in Trueoder FalseWert umzuwandeln .

Alexander Artemenko
quelle
fsteht wahrscheinlich für False, und False == 0so verstehe ich die Logik. Warum die Funktion ein intanstelle von a zurückgeben würde, boolist mir allerdings ein Rätsel.
François Leblanc
@ FrançoisLeblanc, warum es in Datenbanken am häufigsten vorkommt. Wenn es nicht explizit Falseoder 0(Null) ist. Alles andere, was mit der Bool-Funktion ausgewertet wird, wird wahr und gibt Folgendes zurück : 1.
JayRizzo
@ JayRizzo Ich verstehe das und beide sind in den meisten Punkten funktional ähnlich . Dies bedeutet jedoch, dass Sie keinen Singleton-Vergleich verwenden können, d if strtobool(string) is False: do_stuff(). H.
François Leblanc
48

Ein sehr einfacher (aber nicht sehr ausgefeilter) Weg, dies für eine einzige Wahl zu tun, wäre:

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

Sie können auch eine einfache (leicht verbesserte) Funktion schreiben:

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

Hinweis: Verwenden Sie in Python 2 raw_inputanstelle von input.

Danilo Bargen
quelle
7
Ich liebe den ersten Ansatz. Kurz und einfach. Ich habe so etwas wieresult = raw_input("message").lower() in ('y','yes')
Adrian Shum
47

Sie können mit Klick ‚s - confirmMethode.

import click

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

Dies wird gedruckt:

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

Sollte Python 2/3unter Linux, Mac oder Windows funktionieren .

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

Eyal Levin
quelle
24

Wie von @Alexander Artemenko erwähnt, ist hier eine einfache Lösung mit 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
James
quelle
8
nur neugierig ... warum sys.stdout.writestatt print?
Anentropic
2
Beachten Sie, dass strtobool()dies (aus meinen Tests) nicht erforderlich ist lower(). Dies ist jedoch in der Dokumentation nicht explizit.
Michael - Wo ist Clay Shirky
15

Ich weiß, dass dies auf verschiedene Arten beantwortet wurde und möglicherweise nicht die spezifische Frage von OP (mit der Liste der Kriterien) beantwortet, aber dies habe ich für den häufigsten Anwendungsfall getan und es ist weitaus einfacher als die anderen Antworten:

answer = input('Please indicate approval: [y/n]')
if not answer or answer[0].lower() != 'y':
    print('You did not indicate approval')
    exit(1)
Douglas Adams
quelle
Dies funktioniert nicht mit Python 2 - raw_inputwurde inputin Python 3 umbenannt stackoverflow.com/questions/21122540/…
Brian Tingle
9

Sie können auch eine Eingabeaufforderung verwenden .

Schamlos aus der README entnommen:

#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
Ibizaman
quelle
4
Beachten Sie, dass das Verhalten der Eingabeaufforderung ziemlich rückwärts ist, wenn Sie sie mit "default = 'no'" verwenden. Es wird True zurückgegeben, wenn Sie "Nein" wählen, und False, wenn Sie "Ja" wählen.
Rem
7

Ich habe die Antwort von fmark geändert, um mit Python 2/3 kompatibler mehr Python zu machen.

Weitere Informationen finden Sie im Dienstprogrammmodul von ipython, wenn Sie an etwas mit mehr Fehlerbehandlung interessiert sind

# 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)
Bryce Guinta
quelle
Kompatibel mit Python 2 und 3, sehr gut lesbar. Am Ende habe ich diese Antwort verwendet.
François Leblanc
4

Ist dies in 2.7 zu nicht pythonisch?

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

es erfasst zumindest jede Variation von Ja.

Speqtre
quelle
4

Machen Sie dasselbe mit Python 3.x, wo raw_input()es nicht existiert:

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")
pjm
quelle
Nein, das funktioniert nicht. In mehr als einer Hinsicht. Ich versuche gerade, das Problem zu beheben, aber ich denke, dies wird der akzeptierten Antwort sehr ähnlich sein, wenn ich fertig bin.
Gormador
Ich habe dich bearbeitet, um @pjm. Bitte überprüfen Sie es :-)
Gormador
3

Für Python 3 verwende ich diese Funktion:

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

Die Funktion strtobool konvertiert einen String in einen Bool. Wenn die Zeichenfolge nicht analysiert werden kann, wird ein ValueError ausgelöst.

In Python 3 wurde raw_input in input umbenannt .

SuperKeksmann
quelle
2

Sie können so etwas wie den folgenden Code ausprobieren, um mit Auswahlmöglichkeiten aus der hier akzeptierten Variablen "Akzeptiert" arbeiten zu können:

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

Hier ist der Code ..

#!/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
Randy Skretka
quelle
2

Als Programmier-Neuling fand ich eine Reihe der oben genannten Antworten zu komplex, insbesondere wenn das Ziel darin besteht, eine einfache Funktion zu haben, an die Sie verschiedene Ja / Nein-Fragen übergeben können, wodurch der Benutzer gezwungen wird, Ja oder Nein auszuwählen. Nachdem ich diese und mehrere andere Seiten durchsucht und all die verschiedenen guten Ideen ausgeliehen hatte, kam ich zu folgendem Ergebnis:

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')
Mike
quelle
1
Sollte das Argument nicht "Frage" statt "Antwort" heißen?
AFP_555
1

Wie wäre es damit:

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
Visgean Skeloru
quelle
1

Das benutze ich:

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

So würde ich es machen.

Ausgabe

Is it raining today? Specify 'Y' or 'N'
> Y
answer = 'Y'
Callam Delaney
quelle
1

Hier ist meine Meinung dazu: Ich wollte einfach abbrechen, wenn der Benutzer die Aktion nicht bestätigt hat.

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()
ThorSummoner
quelle
0

Ein bereinigtes Python 3-Beispiel:

# 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()
Ian Smith
quelle