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
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 Conversion failed would discard the useful part.
Do not broaden the TypeError caused by a programming defect must still escape with its
Let each owner keep its status
The final contract now has three owners:
mainreturns0after writing and reporting the requested artifact;mainreturns1after an expected catalog boundary failure;argparse raises
SystemExit(0)for help andSystemExit(2)for grammar errors beforemainreaches 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
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
Import
sys.Print the bounded
Could not convert catalog: <cause>message tosys.stderrfor onlyFileNotFoundError,UnicodeDecodeError,csv.Error, and. Return
1for 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
0and grammar-error/status2behavior.Let unexpected programming errors escape unchanged.
Keep import side-effect free and retain the exact guarded
raise SystemExit(main())entry point.