Python Menu-Driven Applications
A Menu-Driven Application is an interactive console program that presents the user with a numbered list of choices, processes their input, executes the corresponding modular function, and loops back until the user explicitly chooses to exit.
# Simple Menu Loop Blueprint:
def show_menu():
print("\n--- ๐ฑ Quick Actions Menu ---")
print("1. View Profile")
print("2. Update Settings")
print("3. Exit")
def app_controller():
# Simulated choices for demo run:
simulated_inputs = ["1", "2", "3"]
for choice in simulated_inputs:
show_menu()
print("Selected Choice:", choice)
if choice == "1":
print("๐ Action: Displaying User Profile...")
elif choice == "2":
print("๐ Action: Updating User Settings...")
elif choice == "3":
print("๐ Exiting program. Goodbye!")
break
app_controller()
The loop continuously prompts the user until the exit condition breaks the control loop.
As CLI applications grow, giant if-elif-elif-else ladders become messy and hard to maintain. Professional Python developers use Dictionary Function Dispatch Tables to route commands in fast $O(1)$ constant time:
# Modular worker functions:
def handle_view(): return "๐ Showing all database records..."
def handle_create(): return "โ Creating new database record..."
def handle_delete(): return "๐๏ธ Deleting specified record..."
def handle_exit(): return "๐ Application closed."
# Function Dispatch Table:
COMMANDS_DISPATCH = {
"1": handle_view,
"2": handle_create,
"3": handle_delete,
"4": handle_exit
}
def execute_command(user_choice):
action = COMMANDS_DISPATCH.get(user_choice)
if action:
return action() # Dynamically invoke the mapped function!
return "โ Invalid selection! Please enter a valid number."
# Test command dispatch:
for choice in ["1", "2", "3", "99", "4"]:
print(f"Command '{choice}' -> {execute_command(choice)}")
Adding a new feature is as easy as writing a new function and registering it in COMMANDS_DISPATCH with zero changes to the core execution loop!
A complete, production-ready menu-driven application featuring account creation, balance inquiry, deposits, withdrawals, and transaction logging:
# =========================================================================
# CAPSTONE PROJECT: MODULAR BANKING & ACCOUNT MANAGEMENT APPLICATION
# =========================================================================
accounts_database = {
"ACC101": {"holder": "Balaji", "balance": 5000.0, "history": []},
"ACC102": {"holder": "Alex", "balance": 2500.0, "history": []}
}
def check_balance(acc_id):
acc = accounts_database.get(acc_id)
if not acc: return f"โ Account {acc_id} not found."
return f"๐ณ Account: {acc['holder']} | Balance: Rs.{acc['balance']:.2f}"
def deposit_funds(acc_id, amount):
acc = accounts_database.get(acc_id)
if not acc: return f"โ Account {acc_id} not found."
if amount <= 0: return "โ Deposit amount must be positive!"
acc["balance"] += amount
acc["history"].append(f"Deposited +Rs.{amount:.2f}")
return f"โ
Deposited Rs.{amount:.2f} successfully! New Balance: Rs.{acc['balance']:.2f}"
def withdraw_funds(acc_id, amount):
acc = accounts_database.get(acc_id)
if not acc: return f"โ Account {acc_id} not found."
if amount > acc["balance"]:
return f"โ Insufficient funds! Current Balance: Rs.{acc['balance']:.2f}"
acc["balance"] -= amount
acc["history"].append(f"Withdrawn -Rs.{amount:.2f}")
return f"โ
Withdrew Rs.{amount:.2f} successfully! Remaining: Rs.{acc['balance']:.2f}"
# Execute banking simulation:
print("--- ๐ฆ Online Banking Simulation ---")
print(check_balance("ACC101"))
print(deposit_funds("ACC101", 1500.0))
print(withdraw_funds("ACC101", 2000.0))
print(withdraw_funds("ACC101", 10000.0)) # Insufficient funds test
print("\nFinal State ACC101:", accounts_database["ACC101"])
- Single Responsibility: Each function does one job (deposit, withdraw, balance check).
- Defensive Validation: Verifies account existence, prevents negative deposits, and guards against overdrafts.
In a dispatch dictionary, store the function name without parentheses (e.g. {"1": my_func}). If you write {"1": my_func()}, the function executes immediately at dictionary creation time rather than when selected!
Build a menu-driven mini inventory app with options to: 1. View Inventory, 2. Add Stock, 3. Sell Stock.
inventory = {"Laptops": 10, "Mice": 25, "Keyboards": 15}
def add_stock(item, qty):
inventory[item] = inventory.get(item, 0) + qty
return f"Added {qty} {item}. Current Stock: {inventory[item]}"
def sell_stock(item, qty):
if inventory.get(item, 0) < qty:
return f"Insufficient stock for {item}!"
inventory[item] -= qty
return f"Sold {qty} {item}. Remaining: {inventory[item]}"
print("Initial Inventory:", inventory)
print(add_stock("Laptops", 5))
print(sell_stock("Mice", 10))
print("Updated Inventory:", inventory)
Q What is a function dispatch table in Python?
A dispatch table is a dictionary mapping user command keys to function reference objects. When a command is selected, Python looks up and executes the mapped function in O(1) time.
Q How do I handle invalid user inputs in a CLI menu gracefully?
Use try-except blocks when converting strings to numbers (e.g. try: choice = int(input()) except ValueError:) and dictionary .get(key) with a default error message.
Q How can I persist data between program executions in a menu app?
Use the built-in json module (json.dump() and json.load()) or the sqlite3 module to save the data dictionary to disk so it reloads automatically on launch.