Skip to content

Instantly share code, notes, and snippets.

@garrettdreyfus
Last active January 18, 2024 15:21
Show Gist options
  • Star 37 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save garrettdreyfus/8153571 to your computer and use it in GitHub Desktop.
Save garrettdreyfus/8153571 to your computer and use it in GitHub Desktop.
Dead simple python function for getting a yes or no answer.
def yes_or_no(question):
reply = str(raw_input(question+' (y/n): ')).lower().strip()
if reply[0] == 'y':
return True
if reply[0] == 'n':
return False
else:
return yes_or_no("Uhhhh... please enter ")
Copy link

ghost commented Feb 18, 2014

@jkbbwr
Copy link

jkbbwr commented Feb 19, 2014

question = lambda q: raw_input(q).lower().strip()[0] == "y" or question(q)

Not safe, far smaller

@AlexandreCollet
Copy link

With a loop:

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

@philipperemy
Copy link

In python3, it's input() instead of raw_input()

@vincenta
Copy link

I suggest using reply[:1] instead of reply[0] to prevent IndexError in case of empty string...

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

@smarlaku820
Copy link

smarlaku820 commented Apr 15, 2018

This must be even more efficient, handling all the errors and Invalid Inputs from the user.

def ask_user():
    check = str(raw_input("Question ? (Y/N): ")).lower().strip()
    try:
        if check[0] == 'y':
            return True
        elif check[0] == 'n':
            return False
        else:
            print('Invalid Input')
            return ask_user()
    except Exception as error:
        print("Please enter valid inputs")
        print(error)
        return ask_user()

Regards
sai

@boreycutts
Copy link

This accounts for other inputs that start with y or n

def yes_or_no(question):
    answer = input(question + "(y/n): ").lower().strip()
    print("")
    while not(answer == "y" or answer == "yes" or \
    answer == "n" or answer == "no"):
        print("Input yes or no")
        answer = input(question + "(y/n):").lower().strip()
        print("")
    if answer[0] == "y":
        return True
    else:
        return False

if yes_or_no("Ayy?"):
    print("Lmao :D")
else:
    print(":(")

@maroc81
Copy link

maroc81 commented Jun 8, 2018

I like @jkbbwr solution's which I modified for a simple script where I want to confirm the user wants to overwrite an existing file.

if not input("Are you sure? (y/n): ").lower().strip()[:1] == "y": sys.exit(1)

I also took the [:1] from @vincenta which will handle an empty response and default to no.

Note: This doesn't handle other responses that start with y and it won't keep prompting. Also, for python 2, use raw_input instead of input

@robertour
Copy link

Correct me if I am wrong but this might be OK with the Assigment Expressions (PEP 572) in Python 3.8

while res:= input("Do you want to save? (Enter y/n)").lower() not in {"y", "n"}: pass

@Jasata
Copy link

Jasata commented Nov 25, 2019

And if you don't like hitting ENTER for whatever reason, something like this might work:

def getch():
    """Read single character from standard input without echo."""
    import sys, tty, termios
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    try:
        tty.setraw(sys.stdin.fileno())
        ch = sys.stdin.read(1)
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    return ch


def yes_or_no(question):
    c = ""
    print(question + " (Y/N): ", end = "", flush = True)
    while c not in ("y", "n"):
        c = getch().lower()
    return c == 'y'


if __name__ == "__main__":
    if not yes_or_no("Continue?"):
        print("NO") # ...or echo nothing and just provide newline
        os._exit(0)
    else:
        print("YES")

Granted, this is very far from "dead simple", but its an alternative nevertheless. (Looking at robertour's suggestion, I wish Debian 10 would have gone with 3.8 instead of 3.7...)

@orangelynx
Copy link

orangelynx commented Apr 21, 2020

What about using strtobool?

def query_yes_no(question, default='no'):
    if default is None:
        prompt = " [y/n] "
    elif default == 'yes':
        prompt = " [Y/n] "
    elif default == 'no':
        prompt = " [y/N] "
    else:
        raise ValueError(f"Unknown setting '{default}' for default.")

    while True:
        try:
            resp = input(question + prompt).strip().lower()
            if default is not None and resp == '':
                return default == 'yes'
            else:
                return distutils.util.strtobool(resp)
        except ValueError:
            print("Please respond with 'yes' or 'no' (or 'y' or 'n').\n")

adapted from this SO question.

@SQB
Copy link

SQB commented Jun 5, 2020

I propose renaming it to whats_it_gonna_be_boy.

@gyoza
Copy link

gyoza commented Nov 5, 2020

I agree :)
image

@shollingsworth
Copy link

Lots of great answers here, but prompted for something a little simpler and recursive.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Simple yes/no function demo."""

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


def main():
    """Run main function."""
    ans = yesno("What'll it be")
    print(f'you answer was: {ans}')



if __name__ == '__main__':
    main()

@icamys
Copy link

icamys commented Nov 29, 2020

Version without recursion:

def single_yes_or_no_question(question, default_no=True):
    choices = ' [y/N]: ' if default_no else ' [Y/n]: '
    default_answer = 'n' if default_no else 'y'
    reply = str(input(question + choices)).lower().strip() or default_answer
    if reply[0] == 'y':
        return True
    if reply[0] == 'n':
        return False
    else:
        return False if default_no else True

@brmaleo
Copy link

brmaleo commented Dec 7, 2020

Correct me if I am wrong but this might be OK with the Assigment Expressions (PEP 572) in Python 3.8

while res:= input("Do you want to save? (Enter y/n)").lower() not in {"y", "n"}: pass

Great idea. A couple more brackets are needed here:

while ( res:=input("Do you want to save? (Enter y/n)").lower() ) not in {"y", "n"}: pass

and then ...

if res=='y':
  ... do something ...

@ozyalhan
Copy link

Lots of great answers here, but prompted for something a little simpler and recursive.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Simple yes/no function demo."""

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


def main():
    """Run main function."""
    ans = yesno("What'll it be")
    print(f'you answer was: {ans}')



if __name__ == '__main__':
    main()

Thank you so much mate, I didn't know that we can return a function that I was manipulating the code in quite different ways. It changed my many lines of stuck code to refactoring.

@willbelr
Copy link

willbelr commented Jun 14, 2021

#!/usr/bin/python3
def confirm_prompt(question: str) -> bool:
    reply = None
    while reply not in ("y", "n"):
        reply = input(f"{question} (y/n): ").lower()
    return (reply == "y")


reply = confirm_prompt("Are you sure?")
print(reply)

Edit: added keyword argument to set either yes or no by default

#!/usr/bin/python3
def prompt(question: str, default=None) -> bool:
    choices = ("", "y", "n") if default in ("yes", "no") else ("y", "n")
    hint = "Y/n" if default == "yes" else "y/n"
    hint = "y/N" if default == "no" else hint
    reply = None

    while reply not in choices:
        reply = input(f"{question} ({hint}): ").lower()
    return (reply == "y") if default != "yes" else (reply in ("", "y"))


reply = prompt("Are you sure?")
print(reply, "\n")

reply = prompt("Are you sure?", default="yes")
print(reply, "\n")

reply = prompt("Are you sure?", default="no")
print(reply, "\n")

@wtfzambo
Copy link

I agree :)
image

@gyoza necrothreading this just to kudos you on the fact that you quoted Meatloaf

@vallamost
Copy link

vallamost commented Nov 27, 2021

Stop using raw_input, that's Python 2.

@marcb4
Copy link

marcb4 commented Dec 21, 2021

How would I add an --yes or -y parser arg to @icamys solution?
first
parser.add_argument("--yes", "-y", help="Always accept")
and then what? :D sorry I am really new to python

maybe something like:

def confirm(question, default_no=True):
    choices = ' [y/N]: ' if default_no else ' [Y/n]: '
    default_answer = 'n' if default_no else 'y'
    reply = str(input(question + choices)).lower().strip() or default_answer
    if reply[0] == 'y':
        return True
    if reply[0] == 'n':
        return False
    if args.yes:
        default_answer='y'
    else:
        return False if default_no else True

but that doesnt work

@stacksjb
Copy link

stacksjb commented Sep 14, 2022

@willbelr, Thank you for this beautiful & elegant solution! I modified with casefold (in Python3) but am otherwise using as-is in a few scripts, and it works great!

def confirm_prompt(question: str) -> bool:
    reply = None
    while reply not in ("y", "n"):
        reply = input(f"{question} (y/n): ").casefold()
    return (reply == "y")


reply = confirm_prompt("Are you sure?")
print(reply)

@matejkonopik
Copy link

My version using simple recursion:

def user_confirm(question: str) -> bool:
    reply = str(input(question + ' (y/n): ')).lower().strip()
    if reply[0] == 'y':
        return True
    elif reply[0] == 'n':
        return False
    else:
        new_question = question
        if "Please try again - " not in question:
            new_question = f"Please try again - {question}"
        return user_confirm(new_question)


if __name__ == "__main__":
    print(user_confirm("Do you love me?"))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment