As a few others mentioned, the argparse module from the stdlib is the way to go for Python. It takes care of most of this for you in an optimized way. Here's a minimal example of the above:
#!/bin/env python3
import argparse
# Setup main parser
parser = argparse.ArgumentParser(
prog="app",
description="App that manages things and jobs",
)
parser.add_argument(
"-v",
"--verbose",
action="store_true",
)
subparsers = parser.add_subparser(
help="Sub commands",
dest="command",
)
# Setup sub-parsers
thing_parser = subparsers.add_parser(
"thing",
help="Manage things",
)
# thing_parser args
thing_parser.add_argument(
"--dry_run",
action="store_true",
help="dry run",
)
thing_parser.add_argument(
"--create",
action="store_true",
help="Create thing",
)
thing_parser.add_argument(
"--name",
action="store",
type=str,
required=True,
nargs="+",
help="Thing name",
)
job_parser = subparsers.add_parser(
"job",
help="Manage jobs",
)
job_parser.add_argument(
"--cancel",
"-c",
action="store_true",
help="Cancel job",
)
job_parser.add_argument(
"--index",
"-i",
action="store",
type=int,
required=True,
nargs="+",
help="Job index",
)
def main():
args=parser.parse_args()
if args.verbose:
print("Verbose mode")
# Match-Case statement for cleaner logic
match args.command:
case "thing":
# thing logic and function calls here
case "job":
# job logic and function calls here
case _:
parser.print_usage()
if __name__ == "__main__":
main()