APT command line interface เหมือนอินพุตใช่หรือไม่?


169

มีวิธีสั้น ๆ ในการบรรลุสิ่งที่อินเตอร์เฟสบรรทัดคำสั่งAPT ( Advanced Package Tool ) ทำใน Python หรือไม่?

ฉันหมายถึงเมื่อผู้จัดการแพคเกจแจ้งคำถามใช่ / ไม่ใช่ตามมา[Yes/no]สคริปต์จะยอมรับYES/Y/yes/yหรือEnter(ค่าเริ่มต้นYesตามตัวอักษรตัวใหญ่ตามคำแนะนำ)

สิ่งเดียวที่ฉันพบในเอกสารอย่างเป็นทางการคือinputและraw_input...

ฉันรู้ว่ามันไม่ใช่เรื่องยากที่จะลอกเลียนแบบ แต่มันก็น่ารำคาญที่จะเขียนใหม่: |


15
ในหลาม 3 ที่เรียกว่าraw_input() input()
Tobu

คำตอบ:


222

ดังที่คุณกล่าวถึงวิธีที่ง่ายที่สุดคือการใช้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 = 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")

ตัวอย่างการใช้งาน:

>>> 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:และฉันอาจส่งคืนบูลีน
Ignacio Vazquez-Abrams

ทางเลือกที่ดี Ignacio แก้ไข
fmark

24
ที่จริงแล้วมีฟังก์ชั่น strtobool ในไลบรารีมาตรฐาน: docs.python.org/2/distutils/ …
Alexander Artemenko

14
สิ่งที่ควรจำ: raw_input()เรียกว่าinput()ใน Python3
nachouve

มีประโยชน์มากจริง ๆ ! เพียงแทนที่raw_input()ด้วยinput()สำหรับ Python3
มูฮัมหมัด Haseeb

93

ฉันจะทำแบบนี้:

# 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()ถูกเรียกinput()ใน Python3
gizzmole

49

มีฟังก์ชั่นstrtoboolในห้องสมุดมาตรฐานของ Python: http://docs.python.org/2/distutils/apiref.html?highlight=distutils.util#distutils.util.strtobool

คุณสามารถใช้มันเพื่อตรวจสอบอินพุตของผู้ใช้และแปลงเป็นค่าTrueหรือFalse


fอาจหมายถึงเท็จและFalse == 0ดังนั้นฉันได้รับตรรกะ ทำไมฟังก์ชั่นถึงคืนค่า a intแทนที่จะboolเป็นความลึกลับสำหรับฉัน
François Leblanc

@ FrançoisLeblancเป็นสาเหตุที่พบบ่อยที่สุดในฐานข้อมูล หากไม่ชัดเจนFalseหรือ0(ศูนย์) อะไรอื่น ๆ 1ที่ได้รับการประเมินโดยใช้ฟังก์ชั่นบูลจะกลายเป็นความจริงและจะกลับมา:
JayRizzo

@ JayRizzo ฉันเข้าใจแล้วและทั้งคู่ต่างก็มีความคล้ายคลึงกันในทางปฏิบัติ if strtobool(string) is False: do_stuff()แต่มันหมายความว่าคุณไม่สามารถใช้เปรียบเทียบเดี่ยวคือ
François Leblanc

48

วิธีที่ง่ายมาก (แต่ไม่ซับซ้อนมาก) ในการทำสิ่งนี้เพื่อตัวเลือกเดียวคือ:

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

หมายเหตุ: ในหลาม 2 ใช้แทนraw_inputinput


7
รักวิธีแรก สั้นและง่าย ฉันใช้สิ่งที่ชอบresult = raw_input("message").lower() in ('y','yes')
Adrian Shum


24

ดังที่ @Alexander Artemenko นี่เป็นวิธีง่ายๆในการใช้ 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
แค่อยากรู้อยากเห็น ... ทำไมsys.stdout.writeแทนที่จะprint?
Anentropic

2
โปรดทราบว่าstrtobool()ไม่ได้ (จากการทดสอบของฉัน) lower()ต้อง สิ่งนี้ไม่ชัดเจนในเอกสารประกอบอย่างไรก็ตาม
ไมเคิล - Clay Shirky อยู่ที่ไหน

15

ฉันรู้ว่าสิ่งนี้ได้รับการตอบแล้วหลายวิธีและนี่อาจไม่ใช่คำตอบเฉพาะของ OP (ด้วยรายการเกณฑ์) แต่นี่คือสิ่งที่ฉันทำสำหรับกรณีการใช้งานทั่วไปและมันง่ายกว่าคำตอบอื่น ๆ :

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

สิ่งนี้ใช้ไม่ได้กับ python 2 - raw_inputถูกเปลี่ยนชื่อเป็นinputpython 3 stackoverflow.com/questions/21122540/ …
Brian Tingle

9

คุณยังสามารถใช้ตัวบอกบท

พร่าจาก 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
ระวังพฤติกรรมของผู้ใช้งานหน้าย้อนหลังสวยเมื่อคุณใช้งานด้วย "default = 'no'"; มันจะกลับมาจริงเมื่อคุณเลือก 'ไม่' และเท็จเมื่อคุณเลือก 'ใช่'
rem

7

ฉันแก้ไขคำตอบของ 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)

เข้ากันได้กับ Python 2 และ 3 อ่านง่ายมาก ฉันลงเอยด้วยการใช้คำตอบนี้
François Leblanc

4

ใน 2.7 นี่มันไม่ไพเราะเกินไปหรือไม่

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

มันจับการเปลี่ยนแปลงของใช่อย่างน้อย


4

ทำแบบเดียวกันกับ 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")

ไม่นี่ใช้ไม่ได้ มากกว่าหนึ่งวิธีจริง ขณะนี้กำลังพยายามแก้ไข แต่ฉันคิดว่านี่จะดูเหมือนคำตอบที่ยอมรับหลังจากทำเสร็จแล้ว
Gormador

ฉันแก้ไขคุณ anwser @pjm โปรดพิจารณาตรวจทาน :-)
Gormador

3

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

กลุ่มสตราโตบูลฟังก์ชันแปลงสตริงเข้าบูล หากไม่สามารถแยกสตริงได้จะเป็นการเพิ่ม ValueError

ในหลาม 3 raw_input ได้รับการเปลี่ยนชื่อการป้อนข้อมูล


2

คุณสามารถลองบางอย่างเช่นโค้ดด้านล่างเพื่อให้สามารถทำงานกับตัวเลือกจากรายการ 'ยอมรับ' ตัวแปรที่นี่:

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

2

ในฐานะที่เป็น noob การเขียนโปรแกรมฉันพบคำตอบข้างต้นที่ซับซ้อนมากเกินไปโดยเฉพาะอย่างยิ่งถ้าเป้าหมายคือการมีฟังก์ชั่นง่าย ๆ ที่คุณสามารถส่งคำถามใช่ / ไม่ใช่เพื่อบังคับให้ผู้ใช้เลือกใช่หรือไม่ หลังจากที่กำจัดสิ่งสกปรกบนหน้านี้และอื่น ๆ อีกหลายอย่างและยืมความคิดที่ดีต่าง ๆ ทั้งหมดฉันลงเอยด้วยสิ่งต่อไปนี้:

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
อาร์กิวเมนต์ไม่ควรถูกเรียกว่า "คำถาม" แทนที่จะเป็น "คำตอบ" ใช่ไหม
AFP_555

1

เกี่ยวกับสิ่งนี้:

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

นี่คือสิ่งที่ฉันใช้:

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

นี่คือวิธีที่ฉันทำ

เอาท์พุต

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

1

นี่คือสิ่งที่ฉันทำฉันต้องการยกเลิกหากผู้ใช้ไม่ยืนยันการกระทำ

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

ตัวอย่าง Python 3 ที่ล้างแล้ว:

# 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()
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.