Files and Data Formats Checkpoint
A review of this module. Skip it if you feel confident; the next module does not need it.
Fix the mistakes
The slips that cost marks in this module. Spot each one, then check the fix.
Test what you know about text files, paths, CSV and JSON. Every program creates the file it reads, so each one runs as a single file.
Pick the right tool
Plain text suits notes and logs. CSV suits flat tables. JSON suits nested data. Use with for every file, and name the encoding.
import csvimport json
with open("notes.txt", "w", encoding="utf-8") as f: f.write("first\nsecond\n")with open("t.csv", "w", newline="") as f: csv.writer(f).writerow(["Asha", 82])with open("d.json", "w") as f: json.dump({"name": "Asha"}, f)with open("notes.txt", encoding="utf-8") as f: print(f.read().splitlines())with open("t.csv", newline="") as f: print(next(csv.reader(f)))with open("d.json") as f: print(json.load(f))Example 1 · Text, CSV and JSON side by side
import csvimport json
with open("t.csv", "w", newline="") as f: csv.writer(f).writerow(["Asha", 82])with open("t.csv", newline="") as f: row = next(csv.reader(f))print(row)print(json.dumps({"name": row[0], "mark": int(row[1])}))['Asha', '82']
{"name": "Asha", "mark": 82}What this code does
- The CSV value
'82'is text, sointconverts it. - The JSON text shows the dictionary built from the row.
Each format gives a different Python type back: a list of lines, a list of strings for a CSV row, and a dictionary for JSON. Notice the CSV mark comes back as the string '82'.
Read, change, write back
A common job is to load data, change it and save it. Read the whole file first, then open it again for writing, so a crash in between cannot leave a half-written file.
import json
with open("cart.json", "w") as f: json.dump({"items": ["pen"]}, f)
with open("cart.json") as f: cart = json.load(f)cart["items"].append("book")with open("cart.json", "w") as f: json.dump(cart, f)
with open("cart.json") as f: print(json.load(f)["items"])Example 2 · Update a JSON file
import json
with open("cart.json", "w") as f: json.dump({"items": ["pen"]}, f)with open("cart.json") as f: cart = json.load(f)cart["items"].append("book")with open("cart.json", "w") as f: json.dump(cart, f)with open("cart.json") as f: print(json.load(f)){'items': ['pen', 'book']}What this code does
- The file is read fully before it is opened again for writing.
- The saved list now holds two items.
The first open for reading finished before the second open erased the file with "w". Doing both at once with "w" would delete the data before it was read.
A missing or broken file
Files can be missing and text can be invalid. Catch FileNotFoundError and json.JSONDecodeError separately, so each problem gets its own clear answer.
import json
def load(name): try: with open(name) as f: return json.load(f) except FileNotFoundError: return "missing" except json.JSONDecodeError: return "broken"
with open("bad.json", "w") as f: f.write("{oops")print(load("none.json"))print(load("bad.json"))Example 3 · Friendly answers for bad files
import json
def load(name): try: with open(name) as f: return json.load(f) except FileNotFoundError: return "missing" except json.JSONDecodeError: return "broken"
with open("bad.json", "w") as f: f.write("{oops")print(load("none.json"))print(load("bad.json"))missing broken
What this code does
- A missing file and a broken file raise different errors.
- Each error gets its own answer.
Each except handles one kind of failure. The first call has no file. The second finds a file, but its text is not valid JSON.
Finish up
Mark complete & continue
Next: Must-do problems: Files and Data Formats