How to Build an argparse Command-Line Tool in Python

Create a simple file-info CLI with argparse that counts lines and prints file size, with optional verbose and output flags.

Easy Python 3.9+ Aug 9, 2026 Automation & scripting 14 views 0 copies

Python code

51 lines
Python 3.9+
import argparse
import os
from pathlib import Path


def process_file(filepath, verbose=False):
    """Read a file and report its size and line count."""
    path = Path(filepath)
    if not path.exists():
        raise FileNotFoundError(f"File not found: {filepath}")

    content = path.read_text()
    lines = content.splitlines()
    size_kb = path.stat().st_size / 1024

    if verbose:
        print(f"Processing: {path}")
        print(f"Lines: {len(lines)}")
        print(f"Size: {size_kb:.2f} KB")
    else:
        print(f"{path}: {len(lines)} lines, {size_kb:.2f} KB")


def main():
    parser = argparse.ArgumentParser(
        description="Simple file info utility - counts lines and size"
    )
    parser.add_argument("filepath", type=str, help="Path to the file to analyze")
    parser.add_argument(
        "-v", "--verbose", action="store_true", help="Show extended processing details"
    )
    parser.add_argument(
        "-o", "--output", type=str, default=None, help="Write result to a file (optional)"
    )

    args = parser.parse_args()

    try:
        if args.output:
            with open(args.output, "w") as f:
                f.write(process_file(args.filepath, verbose=args.verbose))
        else:
            process_file(args.filepath, verbose=args.verbose)
    except FileNotFoundError as e:
        print(f"Error: {e}")
        return 1
    return 0


if __name__ == "__main__":
    exit(main())

Output

stdout
$ python file_info.py sample.txt
sample.txt: 12 lines, 1.23 KB

$ python file_info.py sample.txt --verbose
Processing: sample.txt
Lines: 12
Size: 1.23 KB

$ python file_info.py missing.txt
Error: File not found: missing.txt

How it works

The argparse module parses command-line arguments from sys.argv automatically when you call parse_args(). The add_argument method defines each expected flag or positional argument — here filepath is required, while -v/--verbose uses action='store_true' to act as a boolean switch. In main(), we call parse_args() to get an object holding the parsed values, then run our logic. The function returns an exit code (0 on success, 1 on file error) which the shell can use to detect whether the script succeeded. Wrapping the work in a main() function keeps the script importable and testable, while the if __name__ == '__main__': guard ensures it only runs when executed directly.

Common mistakes

  • Using `action='store'` instead of `action='store_true'` for flags
  • Forgetting to handle `FileNotFoundError` and letting the script crash
  • Writing output with `print()` instead of returning a string for redirection
  • Hardcoding paths instead of accepting them as positional arguments

Variations

  1. Use `nargs='?'` to make the filepath optional and read from stdin instead
  2. Add `type=Path` (from pathlib) instead of `type=str` for better type hints

Real-world use cases

  • A support script that audits log files on a server to report line counts and sizes before debugging.
  • A build-hook tool developers run locally to validate config files and print formatted summaries.
  • A cron job wrapper that logs file growth metrics and streams output to a monitoring dashboard.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Automation & scripting

Related tutorials and quizzes for this topic.