Python’s getopt module parses command-line arguments in the Unix C-style getopt(3) tradition, useful for porting C/shell scripts or building minimal CLI parsers. import getopt. Parse: opts, args = getopt.getopt(argv, shortopts, longopts=[]) — argv is typically sys.argv[1:]; shortopts is a string like "hvo:" where a colon means the option requires a value (e.g., -o value); longopts is a list like ["help", "verbose", "output="] where = means the option requires a value (e.g., --output=file); returns opts as a list of (option, value) tuples (value is "" for flags) and args as the list of non-option arguments. GNU mode: getopt.gnu_getopt(argv, shortopts, longopts) — same signature but allows options to appear after positional arguments (standard getopt stops at the first non-option). Errors: getopt.GetoptError — raised for unknown options or missing required values; .msg → human-readable description; .opt → the offending option string. Claude Code generates CLI tools, option processors, subcommand dispatchers, and legacy script adapters.
CLAUDE.md for getopt
## getopt Stack
- Stdlib: import getopt, sys
- Parse: opts, args = getopt.getopt(sys.argv[1:], "hvo:", ["help","verbose","output="])
- for opt, val in opts:
- if opt in ("-h", "--help"): ...
- if opt in ("-o", "--output"): output = val
- GNU: gnu_getopt # allows options after positional args
- Error: except getopt.GetoptError as e: print(e.msg)
- Note: Prefer argparse for new code; getopt for porting C/shell scripts
getopt Command Line Parser Pipeline
# app/getoptutil.py — parser, schema, dispatch, help, subcommands
from __future__ import annotations
import getopt
import os
import sys
from dataclasses import dataclass, field
from typing import Any
# ─────────────────────────────────────────────────────────────────────────────
# 1. Option schema and typed parser
# ─────────────────────────────────────────────────────────────────────────────
@dataclass
class OptDef:
name: str # long name without --
short: str # single char without -, or "" if none
takes_value: bool = False # True if option requires an argument
default: Any = None
help: str = ""
def build_getopt_strings(
opts: list[OptDef],
) -> tuple[str, list[str]]:
"""
Build the shortopts string and longopts list from OptDef objects.
Example:
opts = [OptDef("help","h"), OptDef("output","o",True,"out.txt")]
shortopts, longopts = build_getopt_strings(opts)
"""
short_parts = []
long_parts = []
for opt in opts:
if opt.short:
short_parts.append(opt.short + (":" if opt.takes_value else ""))
long_parts.append(opt.name + ("=" if opt.takes_value else ""))
return "".join(short_parts), long_parts
def parse_opts(
argv: list[str],
opts: list[OptDef],
gnu: bool = False,
) -> tuple[dict[str, Any], list[str]]:
"""
Parse argv against a list of OptDef, returning (values_dict, positional_args).
Values default to OptDef.default if option not provided.
Example:
opts = [
OptDef("help", "h", False, False, "Show help"),
OptDef("verbose", "v", False, False, "Verbose output"),
OptDef("output", "o", True, "-", "Output file"),
]
values, args = parse_opts(sys.argv[1:], opts)
if values["help"]: print_help(opts)
"""
short_str, long_list = build_getopt_strings(opts)
by_short = {"-" + o.short: o for o in opts if o.short}
by_long = {"--" + o.name: o for o in opts}
values = {o.name: o.default for o in opts}
try:
pairs, positional = (
getopt.gnu_getopt(argv, short_str, long_list)
if gnu
else getopt.getopt(argv, short_str, long_list)
)
except getopt.GetoptError as e:
raise SystemExit(f"Error: {e.msg}") from e
for opt_str, val in pairs:
opt_def = by_short.get(opt_str) or by_long.get(opt_str)
if opt_def is None:
continue
values[opt_def.name] = val if opt_def.takes_value else True
return values, positional
# ─────────────────────────────────────────────────────────────────────────────
# 2. Help formatter
# ─────────────────────────────────────────────────────────────────────────────
def format_help(
prog: str,
opts: list[OptDef],
usage: str = "[options] [args...]",
description: str = "",
) -> str:
"""
Format a help string from a list of OptDef objects.
Example:
print(format_help("mytool", opts, description="Process files"))
"""
lines = [f"Usage: {prog} {usage}"]
if description:
lines += ["", description]
lines += ["", "Options:"]
for opt in opts:
short = f"-{opt.short}, " if opt.short else " "
value_hint = " <val>" if opt.takes_value else " "
default = f" (default: {opt.default!r})" if opt.default not in (None, False, "") else ""
lines.append(f" {short}--{opt.name}{value_hint} {opt.help}{default}")
return "\n".join(lines)
# ─────────────────────────────────────────────────────────────────────────────
# 3. Subcommand dispatcher
# ─────────────────────────────────────────────────────────────────────────────
@dataclass
class Subcommand:
name: str
fn: "callable"
opts: list[OptDef] = field(default_factory=list)
help: str = ""
class CommandDispatcher:
"""
Minimal subcommand dispatcher built on getopt.
Example:
dispatcher = CommandDispatcher("mytool")
@dispatcher.command("compress", help="Compress files")
def compress_cmd(values, args):
level = values.get("level", "6")
print(f"Compress {args} at level {level}")
dispatcher.dispatch(sys.argv[1:])
"""
def __init__(self, prog: str):
self.prog = prog
self._commands: dict[str, Subcommand] = {}
self._global_opts: list[OptDef] = [
OptDef("help", "h", False, False, "Show this help"),
]
def command(
self,
name: str,
opts: list[OptDef] | None = None,
help: str = "",
):
"""Decorator to register a subcommand handler."""
def decorator(fn):
self._commands[name] = Subcommand(
name=name, fn=fn,
opts=(opts or []) + [OptDef("help", "", False, False, "")],
help=help,
)
return fn
return decorator
def _print_usage(self):
cmds = " ".join(self._commands)
print(f"Usage: {self.prog} [{cmds}] [options]")
print()
for name, sub in self._commands.items():
print(f" {name:15s} {sub.help}")
def dispatch(self, argv: list[str]) -> int:
"""Parse argv and dispatch to the matching subcommand. Returns exit code."""
if not argv or argv[0] in ("-h", "--help", "help"):
self._print_usage()
return 0
cmd_name = argv[0]
sub = self._commands.get(cmd_name)
if sub is None:
print(f"Unknown command: {cmd_name!r}", file=sys.stderr)
self._print_usage()
return 1
values, args = parse_opts(argv[1:], sub.opts, gnu=True)
if values.get("help"):
print(format_help(f"{self.prog} {cmd_name}", sub.opts, help=sub.help))
return 0
return sub.fn(values, args) or 0
# ─────────────────────────────────────────────────────────────────────────────
# 4. Raw getopt examples
# ─────────────────────────────────────────────────────────────────────────────
def getopt_example_short(argv: list[str]) -> dict:
"""
Parse -h -v -o <file> from argv.
Example:
result = getopt_example_short(["-v", "-o", "out.txt", "file1.txt"])
"""
try:
opts, args = getopt.getopt(argv, "hvo:")
except getopt.GetoptError as e:
return {"error": e.msg}
result: dict = {"verbose": False, "output": None, "help": False, "args": args}
for opt, val in opts:
if opt == "-h":
result["help"] = True
elif opt == "-v":
result["verbose"] = True
elif opt == "-o":
result["output"] = val
return result
def getopt_example_long(argv: list[str]) -> dict:
"""
Parse --verbose --output=<file> --format=<fmt> from argv.
Example:
result = getopt_example_long(["--verbose", "--output=out.csv", "data.txt"])
"""
try:
opts, args = getopt.getopt(argv, "vo:f:", ["verbose", "output=", "format="])
except getopt.GetoptError as e:
return {"error": e.msg}
result: dict = {"verbose": False, "output": None, "format": "text", "args": args}
for opt, val in opts:
if opt in ("-v", "--verbose"):
result["verbose"] = True
elif opt in ("-o", "--output"):
result["output"] = val
elif opt in ("-f", "--format"):
result["format"] = val
return result
# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────
if __name__ == "__main__":
print("=== getopt demo ===")
# ── short options ─────────────────────────────────────────────────────────
print("\n--- getopt_example_short ---")
for argv in [
["-v", "-o", "out.txt", "file.txt"],
["-h"],
["-v", "pos1", "pos2"],
["--unknown"],
]:
result = getopt_example_short(argv)
print(f" {argv} → {result}")
# ── long options ──────────────────────────────────────────────────────────
print("\n--- getopt_example_long ---")
for argv in [
["--verbose", "--output=data.csv", "input.txt"],
["--format=json", "a.txt", "b.txt"],
["-v", "-f", "csv"],
]:
result = getopt_example_long(argv)
print(f" {argv} → {result}")
# ── parse_opts with OptDef schema ─────────────────────────────────────────
print("\n--- parse_opts ---")
opts_def = [
OptDef("help", "h", False, False, "Show help"),
OptDef("verbose", "v", False, False, "Verbose output"),
OptDef("output", "o", True, "-", "Output path"),
OptDef("workers", "w", True, "4", "Number of workers"),
]
for argv in [
["-v", "-o", "result.txt", "src/"],
["--workers=8", "--verbose", "file1", "file2"],
["-h"],
]:
values, args = parse_opts(argv, opts_def)
print(f" {argv}")
print(f" values={values} args={args}")
# ── format_help ───────────────────────────────────────────────────────────
print("\n--- format_help ---")
print(format_help("mytool", opts_def,
description="Process input files with optional compression."))
# ── CommandDispatcher ────────────────────────────────────────────────────
print("\n--- CommandDispatcher ---")
dispatcher = CommandDispatcher("mytool")
@dispatcher.command("run", help="Run the pipeline")
def run_cmd(values, args):
print(f" run verbose={values.get('verbose')} args={args}")
@dispatcher.command("check", help="Validate inputs")
def check_cmd(values, args):
print(f" check args={args}")
for argv in [["run", "-v", "file.txt"], ["check", "a.py", "b.py"], ["--help"]]:
print(f" dispatch({argv})")
dispatcher.dispatch(argv)
print("\n=== done ===")
For the argparse alternative — argparse.ArgumentParser provides automatic --help generation, type conversion, nargs, choices, metavar, subparsers, mutually exclusive groups, and rich error messages — use argparse for all new Python CLI tools; use getopt when porting existing C or shell scripts that follow the exact POSIX getopt(3) option syntax, when adding minimal command-line parsing with zero boilerplate, or when working in an environment where you need identical behavior to a C program’s option parsing. For the click (PyPI) alternative — @click.command(), @click.option(), and @click.argument() decorators build rich CLI applications with automatic help, shell completion, color output, and testing support — use click for polished CLI tools intended for end users; use getopt for internal scripts, quick utilities, or legacy compat where the decoration overhead is unwanted. The Claude Skills 360 bundle includes getopt skill sets covering OptDef with build_getopt_strings()/parse_opts() typed schema parser, format_help() help formatter, CommandDispatcher with @command decorator and subcommand dispatch, and getopt_example_short()/getopt_example_long() pattern examples. Start with the free tier to try command-line parsing patterns and getopt pipeline code generation.