0%

Programs That Take Arguments · practice

Parse the Two Paths

The converter already knows how to read, validate, and write catalog data. A parser should not repeat any of that work. Its job is narrower: turn text into the values main passes to the converter.

argparse is part of Python’s standard library. Nothing needs installing.

Build one parser in one place

Add the import and a whose only job is to describe the interface:

import argparse


def build_parser():
    parser = argparse.ArgumentParser(
        description="Convert a catalog CSV file to validated JSON.",
        allow_abbrev=False,
    )
    parser.add_argument("input_path", help="CSV catalog to read")
    parser.add_argument("output_path", help="JSON catalog to write")
    return parser

The argument names become attributes. Parsing ["source.csv", "result.json"] returns a namespace whose input_path is "source.csv" and whose output_path is "result.json". They remain , which the Chapter 7 file functions already accept.

ArgumentParser also adds -h and --help. Because the same declarations drive parsing and parser-generated help, those two surfaces stay aligned as the interface changes.

allow_abbrev=False keeps the grammar exact. A prefix of a long option is not another secret spelling: undeclared option names remain parser errors.

Give tests and the shell the same entry point

Change the function header to:

def main(argv=None):

Then parse and forward the two values:

args = build_parser().parse_args(argv)
document = convert_catalog(args.input_path, args.output_path)

When argv is None, argparse reads the arguments the shell actually used to start the program. A caller can pass a instead. That is not a test-only back door; it is one interface with two ways of being handed its input, and it is what will let Chapter 10 exercise this command without a shell at all.

Update the success message to use args.output_path. Keep the existing narrow catalog failure handler for now. The next lessons add the option and put its error text on the final stream.

Prove to yourself that the paths really flow through. Run the command with two filenames you have never used before and confirm the output lands where you asked, not in catalog.json. Then run it with --help, and with one path missing, and read what argparse does on its own.

Why does main take argv=None instead of always reading sys.argv?

Task

Add the standard-library argparse boundary to catalog.py.

  • Import argparse.

  • Define build_parser() with the declared description and required input_path and output_path positional . Set allow_abbrev=False so undeclared option spellings remain errors.

  • Change main to main(argv=None) and parse through build_parser().

  • Forward both parsed paths to convert_catalog.

  • Keep the narrow Chapter 7 catalog-error , status 1 on those failures, and status 0 on success.

  • Print the actual requested output path in the success line.

Leave the exact raise SystemExit(main()) guard in place.