Build Your First Python CLI Tool: Argparse, Colors, and Errors
Create a command-line file analyzer in Python using argparse, ANSI color codes, and proper error handling. Follow step-by-step to build a professional-grade CLI tool from scratch.
Here is the article you requested.
Build Your First Python CLI Tool: Argparse, Colors, and Errors
You have written a Python script, run it a few times, and thought, "This would be way more useful if I could just call it from the terminal like a real tool." That feeling is the start of every good CLI tool. Let’s build one together.
We are going to create a simple file analyzer. It will read a text file, count words, and give you the output in a nice, color-coded format. No fluff, just the code that works.
Step 1: Set Up Your Project
First, create a new folder and a Python file. I call mine filealyze.py. You can name it anything.
mkdir filealyzer
cd filealyzer
touch filealyze.py
Open filealyze.py and add the shebang line at the very top. This lets you run it directly from the terminal on Unix-like systems.
#!/usr/bin/env python3
Now, make the file executable:
chmod +x filealyze.py
Step 2: Use argparse for Real Argument Parsing
Forget about sys.argv. Python’s argparse module is built to handle this the right way. It gives you help messages, type checking, and default values for free.
Let’s add two arguments: the file path (required) and a flag to show a detailed word count.
import argparse
def main():
parser = argparse.ArgumentParser(description="Analyze a text file.")
parser.add_argument("filepath", help="Path to the text file")
parser.add_argument("-v", "--verbose", action="store_true", help="Show detailed word frequency")
args = parser.parse_args()
print(f"File to analyze: {args.filepath}")
print(f"Verbose mode: {args.verbose}")
if __name__ == "__main__":
main()
Run it.
python3 filealyze.py sample.txt --verbose
You will see the output. And if you run python3 filealyze.py --help, you get a fully formatted help menu. That is the argparse magic.
Step 3: Add Colorized Output
Reading black and white text is boring. Let’s use ANSI escape codes to add colors. No external libraries needed.
Create a small helper class to manage colors.
class Color:
GREEN = '\033[92m'
YELLOW = '\033[93m'
RED = '\033[91m'
RESET = '\033[0m'
Now, update your print statements.
def analyze_file(filepath, verbose):
try:
with open(filepath, 'r') as f:
content = f.read()
except FileNotFoundError:
print(f"{Color.RED}Error: File not found.{Color.RESET}")
return
words = content.split()
word_count = len(words)
print(f"{Color.GREEN}Total words: {word_count}{Color.RESET}")
if verbose and word_count > 0:
print(f"{Color.YELLOW}--- Word Frequency ---{Color.RESET}")
# simple frequency logic
freq = {}
for w in words:
w = w.lower().strip(".,!?;:\"'")
if w:
freq[w] = freq.get(w, 0) + 1
for word, count in sorted(freq.items(), key=lambda item: item[1], reverse=True)[:10]:
print(f"{word}: {count}")
Look at the output now. The "Error" is red, the total count is green, and the frequency section is yellow. It reads like a professional tool.
Step 4: Handle Errors Like a Pro
A good CLI tool tells you exactly what went wrong and does not crash with a scary traceback. Python gives you the tools to do this cleanly.
First, wrap your file reading logic in a try/except block. We already did that for FileNotFoundError. But you should also catch permission errors and general read errors.
def analyze_file(filepath, verbose):
try:
with open(filepath, 'r') as f:
content = f.read()
except FileNotFoundError:
print(f"{Color.RED}Error: File '{filepath}' not found.{Color.RESET}")
return
except PermissionError:
print(f"{Color.RED}Error: Permission denied for '{filepath}'.{Color.RESET}")
return
except Exception as e:
print(f"{Color.RED}An unexpected error occurred: {e}{Color.RESET}")
return
Next, validate the file content after reading. An empty file is not an error, but it is worth a warning.
words = content.split()
if len(words) == 0:
print(f"{Color.YELLOW}Warning: File is empty.{Color.RESET}")
return
Finally, if your tool takes user input or paths, validate them before you try to use them. For example, check if the path exists using os.path.exists().
import os
if not os.path.exists(filepath):
print(f"{Color.RED}Error: Path does not exist.{Color.RESET}")
return
Step 5: Put It All Together
Here is the final filealyze.py script.
#!/usr/bin/env python3
import argparse
import os
class Color:
GREEN = '\033[92m'
YELLOW = '\033[93m'
RED = '\033[91m'
RESET = '\033[0m'
def analyze_file(filepath, verbose):
if not os.path.exists(filepath):
print(f"{Color.RED}Error: Path does not exist.{Color.RESET}")
return
try:
with open(filepath, 'r') as f:
content = f.read()
except FileNotFoundError:
print(f"{Color.RED}Error: File not found.{Color.RESET}")
return
except PermissionError:
print(f"{Color.RED}Error: Permission denied.{Color.RESET}")
return
except Exception as e:
print(f"{Color.RED}An unexpected error occurred: {e}{Color.RESET}")
return
words = content.split()
if not words:
print(f"{Color.YELLOW}Warning: File is empty.{Color.RESET}")
return
word_count = len(words)
print(f"{Color.GREEN}Total words: {word_count}{Color.RESET}")
if verbose and word_count > 0:
print(f"{Color.YELLOW}--- Top 10 Most Frequent Words ---{Color.RESET}")
freq = {}
for w in words:
w = w.lower().strip(".,!?;:\"'")
if w:
freq[w] = freq.get(w, 0) + 1
for word, count in sorted(freq.items(), key=lambda item: item[1], reverse=True)[:10]:
print(f"{word}: {count}")
def main():
parser = argparse.ArgumentParser(description="Analyze a text file.")
parser.add_argument("filepath", help="Path to the text file")
parser.add_argument("-v", "--verbose", action="store_true", help="Show detailed word frequency")
args = parser.parse_args()
analyze_file(args.filepath, args.verbose)
if __name__ == "__main__":
main()
Why This Matters
You now have a script that behaves like a real command-line tool. It takes named arguments, shows beautiful colored output, and handles errors without crashing. This pattern works for almost any CLI tool you want to build, whether it is a data converter, a log parser, or a file organizer.
If you work with PythonSkillset, you will find that tools like this become your everyday companions. The next time you need to automate something, do not just write a quick script. Build a CLI tool. It will save you time and look impressive on your resume.
Now go test it with a real text file. Run python3 filealyze.py yourfile.txt -v and see your words painted in green and yellow.
Comments
Questions, corrections, and tips stay visible for everyone reading this page.
Join the discussion
No comments yet
Be the first to leave a note — it helps the next reader.