0%

JSON and CSV · practice

Report Malformed Input

The project now rejects bad data where it discovers it. Try the two seeded failures from a temporary line in the editor or the Python console:

read_catalog_csv("bad_catalog.csv")
read_catalog_json("bad_catalog.json")

The first reaches a row whose quantity is many. The second ends before its array and close. They are different failures, and neither should become a mysterious partial catalog.json.

Catch at the user-facing boundary

Low-level should keep raising. Their callers may need the type and exact cause. The boundary in main is where a short, actionable message becomes more useful than a full for expected bad input.

The converter can reasonably expect:

  • FileNotFoundError when the named input is absent;

  • UnicodeDecodeError when a supposed UTF-8 input is not UTF-8;

  • csv.Error for broken CSV quoting;

  • ValueError for the schema and rules. json.JSONDecodeError is a ValueError subclass, so this also covers malformed JSON when the JSON reader is used by another caller.

Catch only that . A broad except Exception would also hide TypeError from a programming mistake inside the converter and mislabel it as bad data.

One deterministic command

Implement main() so it calls:

convert_catalog("catalog.csv", "catalog.json")

On expected failure, print Could not convert catalog: followed by the exception message and return 1. On success, print exactly:

Wrote 3 items to catalog.json.

Use the actual item count from the returned document and return 0.

Keep the existing guarded entry point. The guard makes importing catalog.py safe for tests and other programs, while pressing Run executes the command.

There is a quick way to check that your handler is narrow rather than all-catching. Temporarily add raise TypeError("boom") at the top of convert_catalog and run the program. You want a traceback, not Could not convert catalog: boom. A TypeError there means a defect in your own code, and dressing it up as bad input would send you looking in the wrong file. Remove the line afterwards.

If you are unsure which exceptions belong in the tuple, ask Monty: “Which of these failures mean bad input, and which mean a bug in my code?” That is the line the whole lesson is drawing.

Task

Implement main() around convert_catalog("catalog.csv", "catalog.json").

Catch only FileNotFoundError, UnicodeDecodeError, csv.Error, and ; print the declared failure prefix and return 1. On success, print the actual item count in Wrote N items to catalog.json. and return 0. Leave unexpected programming errors visible.