How to Create Main Menus for CLI Scripts in Python
The aim of this page📝 is to share an approach for the simple creation of terminal menus with Python scripts, ideally utilizing a simple library function for all menus.
2 min readNov 21, 2022
- Given a list
["retry", "abort", cancel"]
- Print the list with numbers next to the list starting from 1
-- MENU --
1. retry
2. abort
3. cancel
3. Return 1-indexed value in the list
Please select the number (e.g. 1): 2
>>> Aborting...
I am building an automation platform hosting scripts in a dedicated folder
- If curious, see the insightful treatment of Platform < The Evolution of Automation at Google < Site Reliability Engineering
- I have scripts in a folder which I execute to get the menu listing all utils with a keystroke (handled by a bash alias)
- …that is a different story altogether, let’s just look at the source code, the most important are the 4 last lines
- ……and of course,
print("running => ", selected_tool)
is just for demo purposes here, I'll look_up a proper utility
# __main__.py
import os
import sys
sys.path.append("./")
sys.path.append("../")
os.chdir(sys.argv[0])
try:
from lib.python.printer import print_header
from lib.python.make_menu import Terminal_Menu
except:
raise
print_header("SNOWPLOW SUPPORT AUTOMATION PLATFORM", fill_char="-")
SSAP_menu = Terminal_Menu(menu_items=next(os.walk("."))[1])
SSAP_menu.print_menu()
selected_tool = SSAP_menu.select_menu_item()
print("running =>", selected_tool)
- Let’s run that
▶ python .\support_utils\
-------------- SUPPORT AUTOMATION PLATFORM -----------------
1 consul_updater
2 defaults_updater
3 example_event_sender
4 log_reducer
Select a number of an item (e.g. 1): 1
running => consul_updater
The menu is a class with members separated into a command method (print) and a query method (get)
- If curious, see Command and Query Separation — Martin Fowler or google the concept
- Let’s look into the
Terminal_Menu
class located inmake_menu.py
""" menu_maker.py """
class Terminal_Menu:
def __init__(self, menu_items: list):
self.menu_items = menu_items
def print_menu(self):
for i, single_item in enumerate(self.menu_items, start=1):
print(i, single_item)
def select_menu_item(self):
selection = int(input("Select an number of an item (e.g. 1): "))
return self.menu_items[selection - 1]
- the object is initialized with a random list — a source for your future menu
- the command
print_menu
usesenumerate()
method to create a numbered/ordered list frommenu_items
(for enumerate, see https://medium.com/p/616cbf2de913) - the query method
select_menu_items()
asks a user for the number and returns the 1-indexed item from a list by decrementing the client input