advanced
Step 20 of 20
Building a CLI Tool
Python Programming
Building a CLI Tool
Command-line interface (CLI) tools are programs that run in the terminal and accept arguments, options, and subcommands. They are essential for automation, system administration, development workflows, and DevOps. Python is an excellent choice for building CLI tools thanks to its readable syntax, rich standard library, and powerful third-party packages. In this lesson, you will learn to build a fully-featured CLI tool using Python's built-in argparse module and see how to structure it for real-world use.
Basic argparse Usage
import argparse
def main():
parser = argparse.ArgumentParser(
description="A simple greeting CLI tool"
)
# Positional argument
parser.add_argument("name", help="Name of the person to greet")
# Optional arguments
parser.add_argument(
"-g", "--greeting",
default="Hello",
help="Greeting to use (default: Hello)"
)
parser.add_argument(
"-n", "--count",
type=int,
default=1,
help="Number of times to greet"
)
parser.add_argument(
"-u", "--uppercase",
action="store_true",
help="Print greeting in uppercase"
)
args = parser.parse_args()
message = f"{args.greeting}, {args.name}!"
if args.uppercase:
message = message.upper()
for _ in range(args.count):
print(message)
if __name__ == "__main__":
main()
# Usage:
# python greet.py Alice
# python greet.py Alice -g "Hi" -n 3
# python greet.py Alice --uppercase
# python greet.py --help
Subcommands
import argparse
import json
import os
DB_FILE = "tasks.json"
def load_tasks():
if os.path.exists(DB_FILE):
with open(DB_FILE, "r") as f:
return json.load(f)
return []
def save_tasks(tasks):
with open(DB_FILE, "w") as f:
json.dump(tasks, f, indent=2)
def cmd_add(args):
tasks = load_tasks()
task = {
"id": len(tasks) + 1,
"title": args.title,
"done": False,
"priority": args.priority
}
tasks.append(task)
save_tasks(tasks)
print(f"Added task #{task['id']}: {task['title']}")
def cmd_list(args):
tasks = load_tasks()
if not tasks:
print("No tasks found.")
return
for task in tasks:
status = "x" if task["done"] else " "
pri = task.get("priority", "medium")
print(f" [{status}] #{task['id']} [{pri}] {task['title']}")
def cmd_done(args):
tasks = load_tasks()
for task in tasks:
if task["id"] == args.task_id:
task["done"] = True
save_tasks(tasks)
print(f"Marked task #{args.task_id} as done.")
return
print(f"Task #{args.task_id} not found.")
def main():
parser = argparse.ArgumentParser(
description="Task Manager CLI"
)
subparsers = parser.add_subparsers(dest="command", help="Available commands")
# 'add' subcommand
add_parser = subparsers.add_parser("add", help="Add a new task")
add_parser.add_argument("title", help="Task title")
add_parser.add_argument(
"-p", "--priority",
choices=["low", "medium", "high"],
default="medium"
)
# 'list' subcommand
subparsers.add_parser("list", help="List all tasks")
# 'done' subcommand
done_parser = subparsers.add_parser("done", help="Mark a task as done")
done_parser.add_argument("task_id", type=int, help="Task ID to complete")
args = parser.parse_args()
if args.command == "add":
cmd_add(args)
elif args.command == "list":
cmd_list(args)
elif args.command == "done":
cmd_done(args)
else:
parser.print_help()
if __name__ == "__main__":
main()
# Usage:
# python tasks.py add "Learn Python" -p high
# python tasks.py add "Buy groceries"
# python tasks.py list
# python tasks.py done 1
Adding Color and Formatting
# ANSI color codes for terminal output
class Colors:
RED = "\033[91m"
GREEN = "\033[92m"
YELLOW = "\033[93m"
BLUE = "\033[94m"
BOLD = "\033[1m"
RESET = "\033[0m"
def success(msg):
print(f"{Colors.GREEN}{msg}{Colors.RESET}")
def error(msg):
print(f"{Colors.RED}Error: {msg}{Colors.RESET}")
def warning(msg):
print(f"{Colors.YELLOW}Warning: {msg}{Colors.RESET}")
def header(msg):
print(f"\n{Colors.BOLD}{Colors.BLUE}{msg}{Colors.RESET}")
print("=" * len(msg))
# Usage in the task manager
header("Task List")
success("Task added successfully!")
error("Task not found.")
Making It Installable
# pyproject.toml
# [project]
# name = "task-cli"
# version = "1.0.0"
# description = "A simple task manager CLI"
# requires-python = ">=3.8"
#
# [project.scripts]
# tasks = "task_cli.main:main"
# After: pip install -e .
# You can run: tasks add "My task"
# Instead of: python tasks.py add "My task"
Pro tip: For more advanced CLI tools, consider using theclickortyperlibrary instead of argparse. Click uses decorators for a cleaner API, while Typer leverages Python type hints to automatically generate CLI interfaces with minimal code. Both handle colors, progress bars, and user prompts elegantly.
Key Takeaways
- Use
argparsefor building CLI tools with positional arguments, optional flags, and subcommands. - Subcommands (like
git commit,git push) organize complex CLI tools into logical operations. - Use
choices,type, anddefaultparameters to validate and process user input automatically. - Add ANSI color codes for better terminal output readability and user experience.
- Make your CLI installable with
pyproject.tomlentry points so users can run it as a system command.
arrow_back Virtual Environments
check_circle Lap Complete!