Explain Codes LogoExplain Codes Logo

Apt command line interface-like yes/no input?

python
prompt-engineering
functions
best-practices
Alex KataevbyAlex Kataev·Dec 15, 2024
TLDR

To create an APT-like yes/no prompt in Python, employ input() in a concise while loop:

choice = input("Continue? [y/n]: ").lower() while choice not in ['y', 'n']: choice = input("Invalid input. Enter 'y' or 'n': ").lower() if choice == 'y': print("Proceeding...") else: print("Aborted.")

This script is a efficient way to solicit, verify, and act based on user input.

Diving deeper // Upgrading your script's experience

When coding user-friendly CLI applications, it's important to predict user behavior to create a seamless experience. Here are a few strategies to optimize your code and provide a near-APT level of interaction.

Just press Enter: strtobool

If you want to emulate APT's functionality where pressing Enter defaults to 'yes', then you're in luck! Python's strtobool function can handle this for you:

from distutils.util import strtobool def query_yes_no(question, default="yes"): """ Ask a yes/no question and return the answer. It is like asking 'Is the Earth round?' and getting 'YAS!' as a response. """ 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: choice = input(question + prompt).lower() if default is not None and choice == '': return valid[default] elif choice in valid: return valid[choice] else: print("'yes' or 'no' only! Or the keyboard cat will chase you 🐈") response = query_yes_no("Continue?") print("Proceeding..." if response else "Aborted.")

Note how this function elegantly handles empty inputs and provides default responses.

Cross-platform compatibility with Click

When you need your CLI application to work reliably across platforms, the Click library is your friend:

import click if click.confirm('Do you want to continue?', default=True): print('Proceeding...') else: print('Aborted.')

With Click's confirm(), you get a higher level of abstraction, making your script more readable and Pythonic. And it takes care of cross-platform quirks - because no one wants to debug why 'Yes' doesn't mean 'yes' on a random OS.

Functionality // Making your script modular

Sometimes it's not about making the code work. It's about making the code work harder for you. Let's take our Y/N prompt script and turn it into a function:

def get_yes_no_input(prompt, error_prompt="Invalid input. Enter 'y' or 'n': "): """ Turn our Y/N prompt into a sharp reusable tool. Also it will stop asking once it gets a cake 🍰 ... kidding, it's 'y' or 'n'. """ choice = input(prompt).lower() while choice not in {'y', 'n'}: choice = input(error_prompt).lower() return choice == 'y' if get_yes_no_input("Continue? [y/n]: "): print("Proceeding...") else: print("Aborted.")

Modularity is key to maintainability. Plus, it makes the script ready for your next coding adventure.

Handling edge cases

To boldly cut beautiful code, you need to prepare for edge cases like:

  • The user enters 'Kumquat' instead of 'Yes' or 'No'
  • The user presses Enter without typing in anything
  • The user enters 'YES' instead of 'yes'

Our previous script examples handle these oddities by using lower() to make everything lowercase and dealing with blank responses.

Offering better feedback

Make your error messages immediate and helpful to improve user experience:

while True: choice = input("Proceed? (yes/no): ").lower() if choice in ['yes', 'y', '']: print("🚦 Green Light: Go ahead!") break elif choice in ['no', 'n']: print("🚦 Red Light: Stop right there!") break else: print("⚠️ Yield Sign: Type 'yes' or 'no'. Not 'maybe'")

Good feedback guides users to the correct responses.

Abstraction time?

If your yes/no prompt keeps cropping up in your scripts, or if you find yourself adding more features to it, it might be time to move it into its own module.