Command-Line Interfaces (argparse)

15 questions found

How do you create a basic command-line argument parser using argparse?

Beginner
Instantiate argparse.ArgumentParser(), call add_argument() for each expected argument, then call parse_args() to parse sys.argv and return a Namespace object with the parsed values as attributes.
import argparse

parser = argparse.ArgumentParser(description="Greet a user")
parser.add_argument("name", help="Name of the person to greet")
args = parser.parse_args()
print(f"Hello, {args.name}!")
# python greet.py Sam  -> "Hello, Sam!"
Real-world example Building a simple CLI script that greets a user by name, passed as a positional command-line argument.

Common follow-ups: What happens automatically if the user runs the script without providing the required 'name' argument?

Functions & Scope

What is the difference between a positional argument and an optional argument (flag) in argparse?

Beginner
A positional argument is REQUIRED and identified by its ORDER on the command line (declared without a leading dash); an optional argument is identified by a FLAG name (starting with '-' or '--') and is optional by default unless you explicitly mark it 'required=True'.
parser.add_argument("filename")               # positional: required, identified by position
parser.add_argument("--verbose", action="store_true")  # optional: identified by --verbose flag

# python script.py data.txt --verbose
Real-world example Requiring a filename as a positional argument while making a --verbose logging flag optional.

Common follow-ups: How would you make an optional-looking flag (like --output) actually REQUIRED?

Data Types & Structures

How do you specify a default value and a type conversion for an argument?

Intermediate
Pass 'default=' to set the value used when the argument is omitted, and 'type=' to specify a callable (like int, float, or a custom function) that argparse applies to convert the raw string input — argparse automatically raises a helpful error if the conversion fails.
parser.add_argument("--count", type=int, default=1, help="Number of times to repeat")
args = parser.parse_args(["--count", "5"])
print(args.count)  # 5 (an actual int, not the string '5')
Real-world example Accepting a numeric --count or --port argument that's automatically validated and converted to an int, with a sensible default.

Common follow-ups: What error does argparse raise (and how does it exit) if the user passes a non-numeric value for a type=int argument?

Exception Handling

How do you restrict an argument's accepted values using the 'choices' parameter?

Intermediate
Pass 'choices=[...]' to restrict the argument to a specific set of allowed values — argparse automatically validates the input against this list and prints a helpful error message listing the valid choices if the user provides something else.
parser.add_argument("--log-level", choices=["debug", "info", "warning", "error"], default="info")
args = parser.parse_args(["--log-level", "invalid"])
# error: argument --log-level: invalid choice: 'invalid' (choose from 'debug', 'info', 'warning', 'error')
Real-world example Restricting a --log-level or --format flag to a specific, known set of valid string values.

Common follow-ups: Can 'choices' be combined with 'type=int' to restrict to a specific set of allowed NUMBERS instead of strings?

Data Types & Structures

How do you accept a variable number of arguments for a single flag, like a list of filenames?

Intermediate
Set 'nargs' to control how many values an argument consumes: '+' requires ONE OR MORE, '*' allows ZERO OR MORE, and a specific integer requires EXACTLY that many — the parsed result becomes a list instead of a single value.
parser.add_argument("--files", nargs="+", help="One or more input files")
args = parser.parse_args(["--files", "a.txt", "b.txt", "c.txt"])
print(args.files)  # ['a.txt', 'b.txt', 'c.txt']
Real-world example Accepting a list of input files to process in a batch CLI tool, like 'mytool --files a.txt b.txt c.txt'.

Common follow-ups: What's the difference in behavior between nargs='+' and nargs='*' when NO values are provided?

Data Types & Structures

How do you implement boolean flags using action='store_true' and action='store_false'?

Intermediate
'action="store_true"' makes a flag default to False and become True if PRESENT on the command line (no value needed after it); 'action="store_false"' is the inverse, defaulting to True and becoming False if present — both avoid needing the user to type an explicit 'True'/'False' string.
parser.add_argument("--verbose", action="store_true", help="Enable verbose output")
parser.add_argument("--no-color", action="store_false", dest="use_color", help="Disable colored output")
args = parser.parse_args(["--verbose"])
print(args.verbose)    # True
print(args.use_color)  # True (default, since --no-color wasn't passed)
Real-world example Implementing a simple --verbose or --debug toggle flag that doesn't require a value, just its presence or absence.

Common follow-ups: How does the 'dest' parameter let a flag named '--no-color' set an attribute actually named 'use_color'?

Functions & Scope

How do you implement subcommands (like 'git commit' or 'git push') using argparse's add_subparsers()?

Advanced
Call add_subparsers() on the main parser to create a subparser group, then add each subcommand as its own separate ArgumentParser (via add_parser()) with its own specific arguments — each subcommand's parsed arguments merge into the same top-level Namespace, distinguished by a 'dest' attribute indicating which subcommand was invoked.
parser = argparse.ArgumentParser(prog="mytool")
subparsers = parser.add_subparsers(dest="command", required=True)

push_parser = subparsers.add_parser("push")
push_parser.add_argument("remote")

commit_parser = subparsers.add_parser("commit")
commit_parser.add_argument("-m", "--message", required=True)

args = parser.parse_args(["commit", "-m", "Initial commit"])
print(args.command, args.message)  # commit Initial commit
Real-world example Building a multi-command CLI tool like a custom deployment or database migration utility with distinct subcommands, each with its own arguments.

Common follow-ups: How would you dispatch to a different handler FUNCTION based on which subcommand (args.command) was actually invoked?

Functions & Scope

How do you group related arguments visually in the generated --help output using argument groups?

Advanced
add_argument_group() creates a labeled section within the parser's help output, letting you organize related arguments (like all authentication-related flags) together for readability, WITHOUT changing how the arguments are actually parsed — it's purely a --help display organization feature.
parser = argparse.ArgumentParser()
auth_group = parser.add_argument_group("authentication")
auth_group.add_argument("--username")
auth_group.add_argument("--password")

output_group = parser.add_argument_group("output options")
output_group.add_argument("--format", choices=["json", "csv"])
# --help now shows these grouped under their respective section headers
Real-world example Organizing a CLI tool's --help output into clear, logical sections (authentication, output, filtering) for a large number of flags.

Common follow-ups: Does argument grouping have any effect on argument PARSING behavior, or is it purely cosmetic for --help?

Modules & Packaging

How do you implement mutually exclusive arguments, where the user must choose EXACTLY ONE of a set of flags?

Advanced
add_mutually_exclusive_group() creates a group where argparse automatically raises an error if the user provides MORE THAN ONE of the group's arguments together; pass 'required=True' to the group to also enforce that AT LEAST ONE must be provided.
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("--verbose", action="store_true")
group.add_argument("--quiet", action="store_true")
# python script.py --verbose --quiet
# error: argument --quiet: not allowed with argument --verbose
Real-world example Enforcing that a CLI tool's output mode is EXACTLY one of --verbose, --quiet, or --normal, never a combination.

Common follow-ups: Can a mutually exclusive group contain MORE than two arguments?

Exception Handling

How do you write a custom 'type=' validation function for argparse that raises a properly-formatted error for invalid input?

Advanced
Define a plain function that takes the raw string argument and either returns the converted/validated value or raises argparse.ArgumentTypeError with a descriptive message — argparse catches this specific exception and formats it into the standard, consistent CLI error output automatically.
def positive_int(value):
    ivalue = int(value)
    if ivalue <= 0:
        raise argparse.ArgumentTypeError(f"{value} is not a positive integer")
    return ivalue

parser.add_argument("--count", type=positive_int)
# python script.py --count -5
# error: argument --count: -5 is not a positive integer
Real-world example Validating that a numeric CLI argument (like a batch size or retry count) is strictly positive, with a clear, standard-format error message.

Common follow-ups: What's the difference between raising ArgumentTypeError versus a regular ValueError inside a custom type function?

Exception Handling

Showing 1–10 of 15