0%

Programs That Take Arguments · practice

Separate Results from Errors

The program now accepts the complete interface, but one Chapter 7 habit still belongs to the old fixed command: expected failures print to stdout. A reusable needs results and diagnostics to stay distinguishable.

Change the destination, not the exception boundary

Import sys, then direct only the expected catalog message to stderr:

except (FileNotFoundError, UnicodeDecodeError, csv.Error, ValueError) as exc:
    print(f"Could not convert catalog: {exc}", file=sys.stderr)
    return 1

Keep the text. Chapter 7’s boundaries produce bounded, deterministic messages that name the failed header, row, field, or file operation. Replacing them with Conversion failed would discard the useful part.

Do not broaden the . A TypeError caused by a programming defect must still escape with its . stderr does not mean “catch everything”; it means expected diagnostics have a separate destination.

Let each owner keep its status

The final contract now has three owners:

  • main returns 0 after writing and reporting the requested artifact;

  • main returns 1 after an expected catalog boundary failure;

  • argparse raises SystemExit(0) for help and SystemExit(2) for grammar errors before main reaches conversion.

The guard remains:

if __name__ == "__main__":
    raise SystemExit(main())

That line turns main’s returned status into the process status when the file runs. It does nothing on import. Do not parse , print, or write an artifact at level: tests and later project code need to import the without accidentally running the command.

The quickest way to see whether you got the two streams right is to separate them in the shell. Run a failing command with > sending stdout to a file. The error should still appear on your screen, and the file should be empty. If the error landed in the file instead, it is going to stdout.

What does raise SystemExit(main()) do?

Task

Finish the ’s stream and status boundary.

  • Import sys.

  • Print the bounded Could not convert catalog: <cause> message to sys.stderr for only FileNotFoundError, UnicodeDecodeError, csv.Error, and .

  • Return 1 for those failures and print nothing to stdout.

  • Keep the exact success line on stdout, with empty stderr and status 0.

  • Preserve argparse’s help/status 0 and grammar-error/status 2 behavior.

  • Let unexpected programming errors escape unchanged.

  • Keep import side-effect free and retain the exact guarded raise SystemExit(main()) entry point.