Antarmuka baris perintah APT seperti input ya / tidak?

169

Apakah ada cara singkat untuk mencapai apa yang dilakukan antarmuka baris perintah APT ( Advanced Package Tool ) dalam Python?

Maksud saya, ketika manajer paket meminta pertanyaan ya / tidak diikuti oleh [Yes/no], skrip menerima YES/Y/yes/yatau Enter(defaultnya Yesseperti diisyaratkan oleh huruf kapital).

Satu-satunya hal yang saya temukan di dokumen resmi adalah inputdan raw_input...

Saya tahu ini tidak sulit untuk ditiru, tetapi menjengkelkan untuk menulis ulang: |

h3.
sumber
15
Dalam Python 3, raw_input()disebut input().
Tobu

Jawaban:

222

Seperti yang Anda sebutkan, cara termudah adalah menggunakan raw_input()(atau hanya input()untuk Python 3 ). Tidak ada cara bawaan untuk melakukan ini. Dari Recipe 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")

Contoh penggunaan:

>>> 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
sumber
elif choice in valid:Dan saya mungkin akan mengembalikan boolean.
Ignacio Vazquez-Abrams
Pilihan yang baik Ignacio, mengubah
tanda
24
Sebenarnya, ada fungsi strtobool di perpustakaan standar: docs.python.org/2/distutils/…
Alexander Artemenko
14
Ingat saja: raw_input()dipanggil input()dengan Python3
nachouve
Memang super membantu! Cukup ganti raw_input()dengan input()untuk Python3.
Muhammad Haseeb
93

Saya akan melakukannya dengan cara ini:

# 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
sumber
8
raw_input()disebut input()dalam Python3
gizzmole
49

Ada fungsi strtobooldalam pustaka standar Python: http://docs.python.org/2/distutils/apiref.html?highlight=distutils.util#distutils.util#distutils.util.strtobool

Anda dapat menggunakannya untuk memeriksa input pengguna dan mengubahnya ke Trueatau Falsenilai.

Alexander Artemenko
sumber
fmungkin singkatan False, dan False == 0, jadi saya mendapatkan logikanya. Mengapa fungsi akan mengembalikan intbukan boolmerupakan misteri bagi saya.
François Leblanc
@ FrançoisLeblanc untuk Mengapa ini paling umum di Database. Jika tidak secara eksplisit Falseatau 0(Nol). Apa saja, yang lain yang dievaluasi menggunakan fungsi bool menjadi benar dan akan kembali: 1.
JayRizzo
@ JayRizzo saya mengerti, dan keduanya secara fungsional serupa dalam banyak hal. Tetapi itu berarti Anda tidak dapat menggunakan perbandingan tunggal, yaitu if strtobool(string) is False: do_stuff().
François Leblanc
48

Cara yang sangat sederhana (tetapi tidak sangat canggih) untuk melakukan ini untuk satu pilihan adalah:

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

Anda juga dapat menulis fungsi sederhana (sedikit ditingkatkan) di sekitar ini:

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

Catatan: Di Python 2, gunakan raw_inputsebagai ganti input.

Danilo Bargen
sumber
7
Cinta pendekatan pertama. Singkat dan mudah. Saya menggunakan sesuatu sepertiresult = raw_input("message").lower() in ('y','yes')
Adrian Shum
47

Anda dapat menggunakan klik 's confirmmetode.

import click

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

Ini akan mencetak:

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

Harus bekerja Python 2/3di Linux, Mac atau Windows.

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

Eyal Levin
sumber
24

seperti yang disebutkan oleh @Alexander Artemenko, inilah solusi sederhana menggunakan 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
sumber
8
hanya ingin tahu ... mengapa sys.stdout.writebukan print?
Anentropic
2
Perhatikan bahwa strtobool()tidak (dari tes saya) memerlukan a lower(). Namun ini tidak eksplisit dalam dokumentasinya.
Michael - Di mana Clay Shirky
15

Saya tahu ini telah dijawab dengan banyak cara dan ini mungkin tidak menjawab pertanyaan khusus OP (dengan daftar kriteria) tetapi ini adalah apa yang saya lakukan untuk kasus penggunaan yang paling umum dan jauh lebih sederhana daripada tanggapan lain:

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
sumber
ini tidak bekerja dengan python 2 - raw_inputdinamai ulang inputdengan python 3 stackoverflow.com/questions/21122540/…
Brian Tingle
9

Anda juga dapat menggunakan pembisik .

Tanpa malu-malu diambil dari 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
ibizaman
sumber
4
Berhati-hatilah bahwa perilaku pembisik cukup mundur ketika Anda menggunakannya dengan "default = 'no'"; itu akan mengembalikan Benar ketika Anda memilih 'tidak' dan Salah ketika Anda memilih 'ya'.
rem
7

Saya memodifikasi jawaban fmark oleh python 2/3 lebih kompatibel dengan pythonic.

Lihat modul utilitas ipython jika Anda tertarik pada sesuatu dengan lebih banyak penanganan kesalahan

# 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
sumber
Kompatibel dengan Python 2 dan 3, sangat mudah dibaca. Saya akhirnya menggunakan jawaban ini.
François Leblanc
4

pada 2.7, apakah ini terlalu non-pythonic?

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

setidaknya menangkap variasi YA.

Pidato
sumber
4

Melakukan hal yang sama dengan python 3.x, di mana raw_input()tidak ada:

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
sumber
Tidak, ini tidak berhasil. Sebenarnya lebih dari satu cara. Saat ini sedang mencoba untuk memperbaikinya, tetapi saya pikir ini akan sangat mirip dengan jawaban yang diterima setelah saya selesai.
Gormador
Saya mengedit Anda anwser @pjm. Silakan pertimbangkan untuk mengulasnya :-)
Gormador
3

Untuk Python 3, saya menggunakan fungsi ini:

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

Fungsi strtobool mengubah string menjadi bool. Jika string tidak dapat diuraikan maka akan meningkatkan ValueError.

Dalam Python 3 raw_input telah diubah namanya menjadi input .

SuperKeksmann
sumber
2

Anda dapat mencoba sesuatu seperti kode di bawah ini untuk dapat bekerja dengan pilihan dari variabel 'diterima' di sini:

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

Ini kodenya ..

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

Sebagai noob pemrograman, saya menemukan banyak jawaban di atas terlalu rumit, terutama jika tujuannya adalah untuk memiliki fungsi sederhana yang dapat Anda berikan berbagai pertanyaan ya / tidak, memaksa pengguna untuk memilih ya atau tidak. Setelah menjelajahi halaman ini dan beberapa orang lain, dan meminjam berbagai ide bagus, saya berakhir dengan yang berikut:

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
sumber
1
Bukankah seharusnya argumen itu disebut "pertanyaan", bukannya "jawaban"?
AFP_555
1

Bagaimana dengan ini:

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

Inilah yang saya gunakan:

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

Beginilah cara saya melakukannya.

Keluaran

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

Inilah pendapat saya, saya hanya ingin membatalkan jika pengguna tidak menegaskan tindakan.

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

Contoh Python 3 yang dibersihkan:

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