Unit 6 – Teachers Guide
Unit 6 · Files, JSON, Errors & Modules
Your day-to-day companion for delivering Unit 6 — pacing, standards, lesson plans, misconceptions, differentiation, and a Python error appendix. Unit 6 is the unit where students' code stops being alone. They learn to talk to files on disk, lean on Python's standard library, recover from errors with try/except, save structured data with JSON, and split projects across multiple files using their own modules. The capstone — the Persistent Contact Vault — turns the Unit 5 vault into real software whose data survives between runs.
👋 Welcome — How to Use This Guide
This Teacher's Guide is your day-to-day companion for delivering Unit 6 of the Code Quest curriculum. Unit 6 is the unit where students' programs stop being alone. Their code now talks to files on disk, leans on Python's standard library, recovers from errors with try/except, speaks the JSON language of every web API, and gets organized across multiple files using their own modules. The capstone — the Persistent Contact Vault — turns the Unit 5 vault into real software whose data survives between runs. It picks up after Unit 5 and assumes students are fluent with all four data structures (list, dict, tuple, string), functions, the SDLC, and the modular thinking from Unit 4.
What this guide contains
- A pacing guide showing how Unit 6 maps to roughly 8–10 class periods. All five lessons run 50 minutes (lesson 5 is a 2-day capstone). Unit 6 carries the heaviest combined "Python toolbox" load of any unit — file I/O, exception handling, JSON, modules, and custom modules all in one stretch.
- A standards & exam crosswalk. Unit 6 is the home of standards 03.01 (file types) and 03.02 (file operations), and provides the deepest coverage of 07.07 (debugging via exception handling).
- A unit vocabulary glossary with all 21 key terms students will encounter — most are concrete Python tools (functions, keywords, modules) they'll use repeatedly for the rest of their career.
- Five detailed lesson plans using the same 7-section format from prior guides.
- An appendix covering file/exception/JSON/import errors:
FileNotFoundError,PermissionError,json.JSONDecodeError,ModuleNotFoundError, the silent bug of forgettingwith, and the classic "circular import" pitfall.
How each lesson plan is structured
Same 7-section format used in prior units:
- At-a-Glance — objective, time, materials, vocabulary, standards box
- Lesson Flow — a 50-minute breakdown: warm-up, instruction, guided practice, lab, exit ticket
- Watch For — the 3–5 most common student misconceptions and how to address each
- Differentiation — early finishers and struggling students
- Discussion Prompts — questions to spark whole-class conversation
- Real-World Connections — answering "why does this matter?"
- Lesson-Specific Vocabulary — terms introduced or reinforced
How to read this in conjunction with the student lessons
- Before class: read this lesson plan (5–10 min) and skim the student HTML, noting the interactive widgets — the Standard Library Explorer in L4 is the unit's marquee tool, with live
random/datetime/math/osplaygrounds - During class: follow the lesson flow; the student HTML is the textbook + lab
- After class: grade Knowledge Checks and labs against this guide's expectations
contact_vault.py (UI) from vault_io.py (disk & timestamps) is exactly the discipline professional projects are built on. The student who internalizes Unit 6 well writes Python that looks like Python from a real codebase from this point forward.
🗺️ Unit 6 Overview
The big picture
Unit 6 is "Files, JSON, Errors & Modules" — the four tools that turn scripts into software. Lesson 1 introduces file I/O with the with open() pattern. Lesson 2 adds try/except for handling the inevitable disasters that file work brings. Lesson 3 introduces JSON — Python's universal data-saving format and the language every web API speaks. Lesson 4 introduces the standard library — Python's giant pre-built toolbox. Lesson 5 teaches custom modules (any .py file is a module) and culminates in the Persistent Contact Vault, the Unit 5 vault upgraded with real disk-backed memory.
What students learn
- Open, read, write, and append to text files using the
with open()pattern - Choose the right file mode:
"r"(read),"w"(write — overwrites),"a"(append),"r+"(read+write) - Read files three ways:
.read(),.readlines(), and the line-by-line iteration pattern (for line in file) - Catch and handle errors gracefully with
try,except,else,finally - Catch specific exceptions (
FileNotFoundError,ValueError) — never bareexcept: - Save and load Python data using JSON with
json.dump/json.load(file) andjson.dumps/json.loads(string) - Recognize that JSON is just nested dicts and lists in text form — Python and JSON look almost identical
- Pretty-print JSON with the
indent=2argument - Import modules from Python's standard library using three forms:
import x,from x import y,import x as y - Use
random(randomness),datetime(timestamps),math(sqrt, π), andos(file paths) - Discover module capabilities with
dir(module)andhelp(function) - Recognize that any
.pyfile is a module — and split projects into multiple files that import each other - Use the
if __name__ == "__main__":guard to make modules both importable AND runnable - Build the Persistent Contact Vault: a two-file architecture (UI + I/O) with full SDLC, error handling, and timestamps
Prerequisites
Units 1–5. Students must be fluent with: variables, all data types, conditionals, both loops, lists, dictionaries (especially .get()), tuples, string methods, functions with parameters & returns, scope, the SDLC, and the algorithm-first planning habit. Unit 6 doesn't introduce new syntax beyond with, try/except, and import — most of the unit is wiring familiar tools to disk.
What comes next
Unit 7 introduces Object-Oriented Programming — classes and methods. Students will learn to bundle data and behavior together into reusable objects. Unit 6's modules become the natural home for those classes. The Persistent Contact Vault from Unit 6 becomes the foundation that Unit 8's Weather Dashboard builds on (real APIs replace local JSON files).
Materials you'll need
- Computers with web browser access (one per student, or pairs)
- Knowledge Pillars CodeSkills Lab access
- Projector or large screen — Unit 6's interactive widgets (Standard Library Explorer in L4 especially) work best in projection
- Whiteboard with multiple colors — used heavily in Lesson 1 (file modes), Lesson 2 (control-flow diagrams for try/except), and Lesson 5 (two-file architecture diagram)
- Optional: printed file-mode reference card (one per student) — tape to monitor for Lesson 1 labs
- Optional: printed standard-library cheat sheet — Lesson 4 students reach for this constantly
⏱️ Pacing Guide
Unit 6 is designed for 8–10 class periods. All five lessons run 50 minutes; Lesson 5 is a 2-day capstone. The unit moves fast — five distinct tools in five lessons — but each tool builds on the last. Don't compress unless your class has shown strong fluency through Unit 5.
Recommended pacing — 9-day plan
| Day | Lesson | Focus | Homework |
|---|---|---|---|
| Day 1 | L1: Reading & Writing Files | What a file is. with open() pattern. File modes. Reading 3 ways. Writing/appending. Lab 6.1A. | Read L1 Section 5 (writing examples) |
| Day 2 | L1: Files (continued) + L2 intro | Finish file labs. Knowledge check. Preview L2 motivation. | Read L2 Sections 1–3 (try/except basics) |
| Day 3 | L2: try / except | Exception types. try/except control flow. Specific exceptions. else/finally. Lab 6.2A. | Read L3 Sections 1–2 (JSON intro) |
| Day 4 | L3: JSON | Why JSON exists. Python ↔ JSON mirror. The 4 functions (dump, load, dumps, loads). Pretty-printing. Safe loading. Lab 6.3A. | Plan a "save my favorites" mini-app |
| Day 5 | L4: Modules & Standard Library | Module concept. Three import forms. Standard Library Explorer (random, datetime, math, os). Recipes. Lab 6.4A. | Read L5 Sections 1–3 (custom modules) |
| Day 6 | L5: Custom Modules | Any .py is a module. The __main__ guard. Two-file project. Walk through capstone scaffold. Plan starts. | Continue planning capstone |
| Day 7 | L5: Capstone (pt 1) | SDLC stages 1–2: Plan + Code. Build vault_io.py first. Then wire contact_vault.py to use it. | Continue building at home |
| Day 8 | L5: Capstone (pt 2) | SDLC stages 3–5: Test + Fix + Maintain. Especially: corrupt-file recovery test. Showcase. Submit. | — |
Compressed 8-day pacing
If you need to compress: combine Day 1 and Day 2 (cover all of Lesson 1 in one period). Most classes can — file I/O is conceptually simple after Unit 5's data-structure work. But the pattern with open() needs repeated practice; if students aren't using it automatically by the end of Day 1, slow down.
Extended 10-day pacing
If your class needs more time: split Lesson 5 across three days. Day 6 covers custom modules in isolation (no capstone yet). Day 7 = capstone Plan + Code. Day 8 = capstone Test + Fix. Day 9 = capstone Maintain + Showcase. The two-file architecture is one of the most professionally valuable concepts in the entire course; give it room.
with open() pattern is intuitive after Unit 5. Lesson 2 (try/except) takes longer than expected because the control flow is genuinely new — students need to TRACE through what runs when an exception fires. Lesson 3 (JSON) often clicks immediately ("oh, it's just dicts as text"). Lesson 4 (standard library) is fun and energetic if you use the Explorer widget heavily. Lesson 5 always benefits from the full 2 days; the two-file architecture is the unit's hinge.
Suggested grading weights for Unit 6
| Component | Weight | Notes |
|---|---|---|
| Lesson Knowledge Checks (×4) | 15% | 3 questions each, completed in-platform |
| Lab Exercises (×8) | 30% | CodeSkills Lab + a few file-on-disk labs in L1 and L3 |
| Persistent Contact Vault Final Project | 45% | Capstone — 100-pt rubric in Lesson 5 plan |
| Class participation | 10% | Whiteboard work, Standard Library Explorer demos, peer testing |
Note: Persistent Contact Vault is the third 45%-weighted capstone in a row (Mad Libs 4.0, Contact Vault, Persistent Contact Vault). The pattern is intentional — second-half-of-year capstones are heavier because they integrate more skills. A student who does well on this capstone has demonstrated end-to-end software thinking: file I/O, error handling, JSON, modules, AND everything from Units 1–5.
🎓 Standards & Exam Crosswalk
This crosswalk shows exactly which Florida CTE standards and Coding Fundamentals exam objectives each lesson addresses. Use this for admin reviews, IEP documentation, or to prove alignment when adopting the curriculum. Unit 6's primary "new" standards are 03.01 (file types), 03.02 (file operations), and 06.02 (troubleshooting in the SDLC). The capstone (Persistent Contact Vault) covers the broadest set of standards in any unit so far — file I/O + JSON + try/except + modules + everything from Units 1–5.
Florida CTE Standards — Course #9009200
Standards from the Florida Department of Education Coding Fundamentals curriculum framework that Unit 6 addresses:
| Standard | Description | Lessons |
|---|---|---|
| 01.01 | Use specialized computer coding software to solve problems. | All (CodeSkills Lab) |
| 01.02 | Demonstrate proficiency using specialized computer software (e.g., Python). | All |
| 02.02 | Explain the components of programming languages. | L1, L2, L3, L4, L5 |
| 03.01 | Identify and describe text-based file types (txt, csv, json). | L1, L3 — primary unit standard |
| 03.02 | Demonstrate basic file operations (open, read, write, close). | L1, L3, L5 — primary unit standard |
| 04.03 | Demonstrate sorting and filtering of data sets. | L5 (vault search/filter) |
| 05.06 | Recognize that more than one algorithm can solve a given problem. | L1 (3 ways to read a file), L2 (try/except patterns) |
| 05.07 | Create a program that implements an algorithm to achieve a given goal. | L5 (Persistent Contact Vault) |
| 06.02 | Apply troubleshooting techniques within the SDLC. | L2, L5 — primary unit standard |
| 06.03 | Apply iterative debugging within the SDLC. | L5 (capstone testing) |
| 07.01 | Describe the structure of a simple program; explain why sequencing is important. | L5 (modular architecture) |
| 07.05 | Explain the types and use of variables in programming. | L1 (file objects), L4 (module-scoped names) |
| 07.07 | Troubleshoot and debug errors in code. | L2, L5 — full depth via exception handling |
Coding Fundamentals Exam Objectives
Exam objectives that Unit 6 prepares students for. Objective 4 (write & debug simple programs) is the unit's flagship; the capstone is its culminating performance task.
| Obj | Title | Coverage in Unit 6 | Lessons |
|---|---|---|---|
| 1 | Core programming concepts | Continued — file I/O and modules are core | L1, L4, L5 |
| 3 | Algorithm understanding & design | Reinforced — capstone planning | L5 |
| 4 | Write and debug simple programs | Full coverage — primary objective for the unit | L1, L2, L3, L4, L5 |
| 5 | Data manipulation | JSON ties Unit 5 data shapes to disk | L3, L5 |
| 7 | Debugging techniques | Full coverage — try/except as systematic recovery | L2, L5 |
Lesson-by-lesson alignment
| Lesson | Florida Standards | Exam Objectives |
|---|---|---|
| L1: Reading & Writing Files | 01.01, 01.02, 02.02, 03.01, 03.02, 07.05 | 1, 4 (primary) |
| L2: try / except | 01.01, 01.02, 02.02, 05.06, 06.02, 06.03, 07.07 | 4, 7 (primary) |
| L3: JSON | 01.01, 01.02, 02.02, 03.01, 03.02, 05.07 | 1, 4, 5 (primary) |
| L4: Modules & Standard Library | 01.01, 01.02, 02.02, 07.05 | 1, 4 (primary) |
| L5: Custom Modules + Persistent Vault | 01.01, 01.02, 02.02, 03.02, 04.03, 05.06, 05.07, 06.02, 06.03, 07.01, 07.05, 07.07 | 1, 3, 4 (primary), 5, 7 |
📖 Unit 6 Vocabulary Glossary
All 21 key terms students will encounter in Unit 6. The "Intro" column shows the lesson where each term first appears. Each lesson plan also includes its own focused vocabulary list. Most of Unit 6's vocabulary is concrete Python — keywords, functions, and modules students will type and run repeatedly.
| Term | Definition | Example | Intro |
|---|---|---|---|
| File | A named chunk of bytes on disk. Text files contain readable characters; binary files contain raw bytes (images, etc). | contacts.json | L1 |
| open() | Built-in function that creates a file object Python can read or write. | open("notes.txt", "r") | L1 |
| with statement | Context manager that auto-closes a file when the block ends — even if an error fires. The pro pattern for file work. | with open(...) as f: | L1 |
| File Mode | The string passed to open() declaring what you'll do: "r" read, "w" write (overwrites), "a" append, "r+" read+write. | open(f, "a") | L1 |
| .read() / .readlines() | Two ways to slurp a file's contents. .read() = one big string. .readlines() = list of lines. | f.read(), f.readlines() | L1 |
| Exception | An error event that interrupts normal program flow. Python raises one when something unexpected happens. | FileNotFoundError | L2 |
| try / except | Block syntax for catching exceptions. Code in try runs; if an exception fires, the matching except runs instead of crashing. | try: ... except: ... | L2 |
| else / finally | Optional add-ons. else runs if try succeeded. finally ALWAYS runs (cleanup). | finally: file.close() | L2 |
| Specific Exception | Catching a NAMED exception (e.g. except FileNotFoundError) rather than a bare except:. The professional pattern. | except ValueError: | L2 |
| Bare except | Catching ALL exceptions with except: — almost always wrong. Hides bugs. Use specific exceptions. | except: ⚠️ AVOID | L2 |
| JSON | JavaScript Object Notation. A text format for structured data. Looks almost identical to Python dicts/lists. The universal data-exchange format. | {"name": "Alex"} | L3 |
| json.dump() / json.load() | FILE versions: dump writes Python data to a file as JSON; load reads JSON from a file back to Python. | json.dump(data, f) | L3 |
| json.dumps() / json.loads() | STRING versions: dumps turns Python data into a JSON STRING; loads parses a JSON string. The "s" = string. | json.dumps(d, indent=2) | L3 |
| Module | A Python file containing reusable code (functions, classes, constants). Loaded with import. | import math | L4 |
| Standard Library | The collection of modules that ship free with every Python install. random, datetime, json, os, math, etc. | No install needed! | L4 |
| import | Keyword that loads a module. Goes at the top of the file. | import random | L4 |
| from / as | Variants of import. from x import y grabs ONE tool. as renames it locally. | from random import randint | L4 |
| random / datetime / math / os | The four standard-library modules students use most. Random numbers, dates & times, math functions, file paths. | random.randint(1, 6) | L4 |
| Custom Module | A .py file YOU wrote that another file imports. Same mechanism as standard library; same syntax. | import vault_io | L5 |
| __main__ | A special variable Python sets to "__main__" when a file is run directly. Used to make modules importable AND runnable. | if __name__ == "__main__": | L5 |
| Two-File Architecture | Splitting a project into a UI/main file plus one or more helper modules. The Unit 6 capstone uses this pattern. | contact_vault.py + vault_io.py | L5 |
open() (talk to files), try/except (handle errors), JSON (save structured data), and import (use other code). Master those four and the rest follow naturally. The five lesson plans each have their own focused vocab subset; this glossary is the unit-wide reference.
📄 Lesson 1 · Reading & Writing Files
Lesson 1 · Reading & Writing Files
Lesson PlanAt-a-Glance
with open() pattern to safely read and write text files, choose the correct file mode ("r", "w", "a") for the task, read files three ways (.read(), .readlines(), line-by-line iteration), and recognize that "w" mode OVERWRITES — a critical safety point.open(), with statement, File Mode, .read(), .readlines()Lesson Flow (50 minutes)
🔥 Warm-Up (5 min)
- Project the Mad Libs 4.0 from Unit 4 with this question: "When you closed the program, where did the words go?" Take answers — they vanished.
- Reveal: today is the day Python's programs stop being amnesiac. We're going to make data SURVIVE. The tool: text files on disk.
🎤 Direct Instruction (15 min)
- Open Lesson 6.1 on the projector. Walk through Section 1 ("What Is a File, Really?"). A file = a named chunk of bytes on disk. Text files are readable; binary files are images, audio, etc. Today is text files.
- Walk through Section 2 ("The
with open()Pattern"). Live-code:with open("notes.txt", "w") as f: f.write("Hello!") - The two parts:
open("filename", "mode")creates a file object;with ... as f:auto-closes it when the block ends — even if an error fires. The professional pattern. - Walk through Section 3 ("File Modes"). Drill the three:
"r"— read existing file. Crashes if it doesn't exist."w"— write. OVERWRITES the entire file. Creates if missing. Drill this safety point."a"— append. Adds to the end. Creates if missing. Use when you don't want to lose existing content.
- Walk through Section 4 ("Reading From a File"). Three ways:
content = f.read()— entire file as one string. Use for small files.lines = f.readlines()— list of lines (with\nat end of each).for line in f:— line-by-line iteration. Memory-efficient for huge files.
- Walk through Section 5 ("Writing to a File").
f.write("text")doesn't add newlines automatically — students must add"\n"themselves if they want one. Common surprise.
🤝 Guided Practice (8 min)
- On the whiteboard, present 4 scenarios. For each, the class names the right mode:
- "Add a new entry to a journal file" →
"a" - "Read student names from a roster" →
"r" - "Replace a file with new content" →
"w" - "Show a help file to the user" →
"r"
- "Add a new entry to a journal file" →
- Live-demo the
"w"safety risk: create a file with content, open it in"w"mode, write nothing, close. Reopen and read — empty. The "w" mode wiped it. Drill this.
💻 Independent Lab (17 min)
- Lab 6.1A — "Journal Writer": students build a tiny journal program. Prompts for an entry, appends to
journal.txtwith a timestamp prefix, then reads back and prints all entries. Required:"a"mode for writes,"r"for reads. - Lab 6.1B — "Word Counter": students read
poem.txt(provided) line-by-line, count total words across all lines, print the count. Required:for line in f:pattern. - Circulate. Common bugs: forgetting
with(file stays open and locked); using"w"when they meant"a"(data wiped on every save — students panic when their journal "loses" entries); forgetting\nwhen writing (everything runs together on one line).
🚪 Exit Ticket (5 min)
- On paper: "What's the difference between
open(f, "w")andopen(f, "a")? Give one example of when you'd use each." - Answer:
"w"overwrites everything in the file;"a"adds to the end. Use"w"when you want to replace (saving a config). Use"a"when you want to add (logging, journals).
⚠️ Watch For — Common Misconceptions
"w" mode appends.""w" mode. Only the LAST one is in the file. Panic. Tears."w" WIPES. It opens the file empty. Whatever was there is GONE. For adding, use "a". The mnemonic: "w" = wipe + write; "a" = add. Recover lost data only if a backup exists; this is why pros version-control everything.with."f = open("x.txt"); content = f.read() with no f.close(). File stays open, gets locked, sometimes data isn't flushed to disk.with open() as f: pattern as the default. It auto-closes — handles cleanup even when errors fire. Manual open()+close() exists but is the wrong pattern for this course. Mark a deduction in the rubric for any file work without with.f.write() adds newlines automatically."f.write("Alex"); f.write("Sam") — file contains "AlexSam" on one line. Surprise.f.write() does NOT add newlines. You must include \n yourself: f.write("Alex\n"). print() adds newlines automatically, but file writes don't. Different functions, different defaults.data1 = f.read(); data2 = f.read() — second read returns empty string. Confusion..read(), the cursor is at the end. To re-read, you'd need to seek back or reopen. For most beginner work: read once, store the result in a variable, use that variable.🎯 Differentiation
For early finishers
Challenge: write a "log file rotator" — read the existing log; if it has more than 100 lines, keep only the last 50; write back. Stretch: researchseek() and tell() (file cursor control) and explain in 2 sentences when they're useful.
For struggling students
Skip Lab 6.1B. Stay on Lab 6.1A and focus on: write to a file with"a", then read back with "r". The win: a working journal that adds entries and reads them. The line-by-line iteration pattern can be revisited.
💬 Discussion Prompts
- Why does Python automatically close files at the end of a
withblock? (Files are scarce OS resources. Open files stay locked. Forgetting to close has historically been a major bug source. Thewithpattern automates the cleanup.) - What kinds of data would you NEVER store in a text file? (Passwords (use hashed storage). Credit cards (use a secure DB). Anything binary like images (use binary mode). Anything that needs concurrent access by many users (use a database — Unit 10).)
- How is reading a file like reading a book? (There's a "cursor" — the page you're on. Once you read forward, you're past those pages. To re-read, you flip back. Files work the same way.)
🌍 Real-World Connections
- Save files in games. Every game-save is a file write — usually JSON or a custom format. When you "load," it's a file read. Same pattern as today's lesson.
- Configuration files. Almost every app has one —
.gitconfig,settings.json,preferences.plist. They're text files with structured data. - Logs. Every server, every web app, every IoT device writes log files — typically in append mode, never overwriting. When something breaks, engineers read the logs to find out what happened.
- Receipts and invoices. When your phone emails you a receipt, somewhere a system wrote a file (or DB record). Files are the basic unit of "data that survives the program."
📖 Lesson-Specific Vocabulary
with statement — Context manager that auto-closes a file when the block ends."r" read, "w" write (overwrites!), "a" append..read() = one big string. .readlines() = list of lines.🛡️ Lesson 2 · try / except — Catching Exceptions Gracefully
Lesson 2 · try / except
Lesson PlanAt-a-Glance
try / except to catch exceptions, name SPECIFIC exception types (never bare except:), trace the control flow when an exception fires, and apply the optional else and finally clauses correctly.try / except, else / finally, Specific Exception, Bare exceptLesson Flow (50 minutes)
🔥 Warm-Up (5 min)
- Project a Lesson-1-style file-read program. Then run it with a filename that doesn't exist. Show the
FileNotFoundErrortraceback. Ask: "Should our program crash like this every time someone makes a typo?" - Reveal: today we learn how to recover instead of crash. The tool:
try / except.
🎤 Direct Instruction (18 min)
- Open Lesson 6.2 on the projector. Walk through Section 1 ("What Is an Exception?"). An exception = an error event Python raises when something unexpected happens. Up till now, exceptions = your program crashes.
- Walk through Section 2 ("The try / except Block"). Live-code:
try: f = open("missing.txt") content = f.read() except FileNotFoundError: print("File not found — using defaults.") content = "" - Walk through Section 3 ("Watch the Control Flow"). On the whiteboard, draw the control flow:
- Try block runs.
- If NO exception: skip the except. Continue past the block.
- If an exception MATCHES: run the except block. Continue past the block.
- If an exception DOESN'T MATCH: propagate up — the program might still crash if no outer except catches it.
- Walk through Section 4 ("Catch Specific Exceptions, Not Everything"). The professional rule: name the exception.
except FileNotFoundError:is right;except:is the WRONG pattern. Bare except catches BugReports too — silencing them. - Walk through Section 5 ("The Full Block: try/except/else/finally"). Drill:
try:— code that might failexcept XError:— runs IF that error fireselse:— runs IF try succeeded (no exception)finally:— ALWAYS runs (cleanup, even on uncaught errors)
- Walk through Section 6 ("Real-World Patterns"). Three patterns students will use constantly:
- Safe file open:
FileNotFoundError→ use defaults - Safe int conversion:
ValueError→ re-prompt user - Safe dict lookup:
KeyError→ use.get()instead (cheaper)
- Safe file open:
🤝 Guided Practice (7 min)
- On the projector, walk through 3 broken programs. For each, students name the exception type and write the right except clause:
int("abc")→ValueErrornums[10]on a 5-item list →IndexError5 / 0→ZeroDivisionError
- Reinforce: each one is a SPECIFIC exception. Bare
except:would catch all 3 — but students wouldn't know which fired.
💻 Independent Lab (15 min)
- Lab 6.2A — "Safe Calculator": students write a program that asks for two numbers and divides them. Must handle TWO exceptions:
ValueError(user types non-number) andZeroDivisionError. Each gets its ownexceptclause with a friendly message. - Lab 6.2B — "Resilient File Reader": students write a function
load_safely(filename)that reads a file. OnFileNotFoundError, returns"(no file yet)". On any OTHER error, lets it propagate (don't catch what you don't know how to handle). - Circulate. The biggest anti-pattern: bare
except:. Stop students from writing it. Make them name the specific exception.
🚪 Exit Ticket (5 min)
- On paper: "Why is
except:(bare) almost always the wrong choice? Name two reasons." - Looking for: (1) it catches BUGS — silently hides programmer errors. (2) it catches keyboard interrupts (Ctrl-C) — making the program impossible to quit. Either alone earns the point.
⚠️ Watch For — Common Misconceptions
except: is the safe choice."except: with no exception name. The program no longer crashes — but it ALSO swallows real bugs silently. Worse than crashing.except FileNotFoundError:. except ValueError:. The unnamed form is the wrong pattern in 99% of cases. Mark deductions on the rubric.else runs whether try succeeded or not."else runs vs finally.else = "things ran fine, here's what to do next." Only runs if try succeeded with no exception. finally = "no matter what happened, do this cleanup." Always runs. Drill with a control-flow diagram on the whiteboard.except FileNotFoundError wrapping int(input()). The exception fires, doesn't match, propagates, program crashes. Student doesn't know why.except.🎯 Differentiation
For early finishers
Challenge: write a "robust input function"get_int(prompt) that loops until the user gives a valid integer. Use while True: + try/except ValueError + break. Stretch: research the raise keyword and explain when you'd raise an exception yourself rather than catch one.
For struggling students
Skip Lab 6.2B. Stay on Lab 6.2A and focus on a SINGLE try/except handling ONE specific exception. The win: their division program doesn't crash on letters or zero.💬 Discussion Prompts
- What's the difference between an EXCEPTION and a BUG? (Bug = a programmer error, the code is wrong. Exception = an EVENT, an unexpected condition that the code might not control. File missing isn't a bug; division by zero might or might not be — depends on whether you should have validated input first.)
- Which is "better" — preventing errors, or recovering from them? (Both are needed. Some things you can prevent (validate input). Some you can't (network goes down, file gets deleted by another program). Use prevention when possible; use try/except for what's beyond your control.)
- If your program catches an exception, should it ALWAYS recover silently? (No. Sometimes you catch, log the error, and re-raise. Sometimes you catch and convert to a friendlier error. The right move depends on context. The wrong move is ALWAYS to swallow silently.)
🌍 Real-World Connections
- Every web request. When an app fetches data from the internet, the server might be down, slow, or unreachable. Apps use try/except (or equivalent) to gracefully retry or show "connection error" — never to crash.
- Banking software. Try/except is mandatory in financial code. A network glitch in the middle of a transfer can't crash the program — money is at stake. Robust error handling is a regulatory requirement.
- Self-driving cars. Sensor data sometimes fails. The car can't crash (literally) when one camera goes offline. It must catch the failure and keep running on the remaining sensors.
- Mars rovers. NASA can't reboot a rover from Earth quickly. Every line of rover code is wrapped in defensive error handling. A crashed rover is millions of dollars lost.
📖 Lesson-Specific Vocabulary
else runs if try succeeded. finally ALWAYS runs.except:. Almost always wrong.📦 Lesson 3 · JSON — Saving Structured Data
Lesson 3 · JSON
Lesson PlanAt-a-Glance
json functions correctly (dump/load for files, dumps/loads for strings), pretty-print JSON with indent=2, and combine JSON with try/except to load files safely.json.dump(), json.load(), json.dumps(), json.loads()Lesson Flow (50 minutes)
🔥 Warm-Up (5 min)
- Project a Unit 5 contact dict:
{"name": "Alex", "phone": "555-1234"}. Ask: "What if I want to save this to a file?" Take answers — students suggest writing strings, parsing on read, etc. - Reveal: there's already a universal solution that EVERY app on the planet uses. It's called JSON. And the best part — it looks almost EXACTLY like Python.
🎤 Direct Instruction (15 min)
- Open Lesson 6.3 on the projector. Walk through Section 1 ("Why Do We Need JSON?"). Without JSON, saving a dict requires hand-rolled string parsing. With JSON, one line. Plus: every modern web API speaks JSON.
- Walk through Section 2 ("Python & JSON Look Almost Identical"). Project both side by side:
Python: {"name": "Alex", "tags": ["a", "b"]} JSON: {"name": "Alex", "tags": ["a", "b"]} - The differences: JSON keys must be strings in double quotes. JSON has
true/false/null(lowercase) instead of Python'sTrue/False/None. JSON tuples don't exist — they become lists. That's it. - Walk through Section 3 ("Try the Translation Yourself"). Use the lesson's interactive translator. Project. Click through 3–4 examples; have the class predict the JSON output before reveal.
- Walk through Section 4 ("The Four Functions of
json"). Drill the matrix:json.dump(data, file)— write Python data to FILE as JSONjson.load(file)— read JSON FILE back to Python datajson.dumps(data)— convert Python data to a JSON STRINGjson.loads(string)— parse a JSON STRING back to Python
- The "s" suffix = string.
dump/load= files.dumps/loads= strings. Drill this distinction — students confuse them constantly. - Walk through Section 5 ("Pretty-Print").
json.dump(data, f, indent=2)— adds indentation, makes the file human-readable. Default is one giant line. Use indent for any file a human will look at. - Walk through Section 6 ("Safe Loading"). Combine with Lesson 2's try/except:
try: with open("data.json") as f: data = json.load(f) except (FileNotFoundError, json.JSONDecodeError): data = [] # start fresh - Two exceptions to catch: file missing (FileNotFoundError) AND file corrupted (json.JSONDecodeError). The capstone explicitly tests both.
🤝 Guided Practice (8 min)
- On the whiteboard, walk through writing a Unit-5 vault to JSON, then reading it back. Show that the data round-trips perfectly — except tuples become lists. (This is why the capstone's location is documented as a list-not-tuple after JSON: a known gotcha.)
- Show a real-world JSON file (a GitHub API response works well — paste a small one). The class identifies the dict, the lists inside it, the nested structures. Same shape they've been building all year.
💻 Independent Lab (17 min)
- Lab 6.3A — "Save My Profile": students build a Python dict representing themselves (5+ keys, including a list of hobbies). Save to
profile.jsonwith indent=2. Open the file in a text editor and verify it's readable. Then read it back into a new variable and verify it matches. - Lab 6.3B — "Safe Loader": students write a function
load_data(filename)that uses try/except to handle BOTH FileNotFoundError AND JSONDecodeError. Returns an empty dict on either error. Test by deleting the file (recovers); corrupting the file by hand (recovers). - Circulate. Common bug: confusing
dumpwithdumps.dumptakes a file;dumpstakes nothing extra. The "s" matters.
🚪 Exit Ticket (5 min)
- On paper: "Match each function to what it does:"
json.dumpjson.loadjson.dumpsjson.loads
- Answers: 1A, 2B, 3C, 4D. Common error: getting
dump/dumpsswapped. The "s" = string is the mnemonic.
⚠️ Watch For — Common Misconceptions
dump vs dumps."json.dumps(data, file). Crashes — dumps doesn't take a file. Or: json.dump(data) — crashes, missing the file argument.dump writes to a FILE; dumps RETURNS a string. Drill the matrix on the whiteboard. The exam tests this distinction directly.{name: "Alex"}). json.load crashes with JSONDecodeError.(40.7, -74.0) with json.dump, reads it back, and is confused that it's now a list [40.7, -74.0].location field is documented as a list-after-JSON for this reason.indent=2 for files a human might open. The default (no indent) is for transmission over wires where size matters. For human eyes: indent.except (FileNotFoundError, json.JSONDecodeError):. The tuple syntax catches either. The capstone tests this explicitly — it's worth 15 of 100 rubric points.🎯 Differentiation
For early finishers
Challenge: research howrequests + JSON power web APIs. Make a tiny "fetch a joke" program using requests.get(...).json() against a public joke API. Stretch: explore json.dumps(data, indent=2, sort_keys=True) and explain why sorted keys matter for diffs in version control.
For struggling students
Stay on Lab 6.3A. Skip the safe loader. The win: save a profile dict to JSON, open the file, and read it back. The four-function matrix can be revisited; for now they need justdump and load.
💬 Discussion Prompts
- Why did JSON win? It's not the only data format — there's XML, YAML, CSV, others. (Simplicity. JSON is small, readable, language-agnostic. It looks like Python (and JavaScript). Easy to parse. Just enough features. Often "good enough beats best.")
- Could you store a Python function in JSON? (No. JSON has no function/class type. It can store DATA only — strings, numbers, booleans, lists, dicts, null. To save a function, you'd need a different mechanism (pickle in Python, but that's risky).)
- What does it mean that "JSON is a data format"? (It defines what shapes data can take. It does NOT define what those shapes mean — that's the application's job. JSON is the envelope; the contents are up to you.)
🌍 Real-World Connections
- Every web API on the planet. When your phone fetches data from a server, 99% of the time it comes back as JSON. Reading JSON is the most fundamental "talk to the internet" skill.
- Configuration files.
package.json(Node.js),tsconfig.json(TypeScript),composer.json(PHP), VS Code settings — JSON is everywhere developers configure things. - Game saves. Modern game saves are JSON or close-to-JSON. Some games (Stardew Valley, Civilization VI) use plain JSON you can edit by hand.
- NoSQL databases. MongoDB, Firebase, DynamoDB all store JSON-like documents. Master JSON now and you've previewed how the world's modern databases work.
📖 Lesson-Specific Vocabulary
dump writes Python → JSON; load reads JSON → Python.dumps = Python → JSON string; loads = JSON string → Python.📦 Lesson 4 · Modules & the Standard Library
Lesson 4 · Modules & the Standard Library
Lesson PlanAt-a-Glance
import (import x, from x import y, import x as y), apply four standard-library modules (random, datetime, math, os), and discover module capabilities with dir() and help().import, from, as, random, datetime, math, osLesson Flow (50 minutes)
🔥 Warm-Up (5 min)
- Ask the class: "How would you generate a random number from 1 to 6 in Python?" Take answers — most students will start writing some kind of formula or guess.
- Reveal: someone already wrote it.
import random; random.randint(1, 6). Done. Today is the day students stop reinventing wheels.
🎤 Direct Instruction (15 min)
- Open Lesson 6.4 on the projector. Walk through Section 1 ("What Is a Module?"). A module = a Python file containing reusable code. Students have used one already:
import jsonin Lesson 3. Today: meet the rest of the toolbox. - The standard library = modules that ship with Python. No install. Just
import. - Walk through Section 2 ("Three Ways to Import"):
import random— load the whole module. Use asrandom.randint(...).from random import randint— load just one function. Use asrandint(...).import datetime as dt— load with a shorter alias. Use asdt.datetime.now().
- The PEP 8 rule: imports go at the TOP of the file, one per line.
- Walk through Section 3 ("Try Each Module — Live"). Open the Standard Library Explorer widget. Project. Click through:
random.randint(1, 6),random.choice([...]),random.shuffle([...])datetime.now(),datetime.now().strftime("%Y-%m-%d %H:%M")math.sqrt(16),math.pi,math.ceil(3.2)os.path.exists("file.txt"),os.listdir(".")
- Walk through Section 4 ("Real Recipes Using These Modules"). Five recipes: random greetings, timestamps for saves, dice rolls, distance formula, "check if file exists before opening." All real, all reusable.
- Walk through Section 5 ("Discovering What a Module Can Do"). Two discovery tools:
dir(random)— lists everything in the modulehelp(random.randint)— shows the docstring/usage
- Pros use these constantly. They DON'T memorize the standard library — they look things up.
🤝 Guided Practice (8 min)
- On the whiteboard, present 5 problems. For each, students name the right module:
- "Pick a random winner" →
random.choice - "Get today's date" →
datetime.datetime.today() - "Compute a square root" →
math.sqrt - "Check if a save file exists" →
os.path.exists - "Wait for 3 seconds" →
time.sleep(3)(introduce time module briefly)
- "Pick a random winner" →
- Reinforce: the question to ask is always "is there a module for this?" The answer is almost always yes.
💻 Independent Lab (17 min)
- Lab 6.4A — "Use Three Modules": students write a single program that uses ALL THREE import forms. Roll a random die (
import random), greet with the date (from datetime import datetime), compute a circle's area (import math as m). Each form used at least once. - Lab 6.4B — "Discover & Use": students pick ONE module they haven't seen (
statistics,string,collections) and usedir()+help()to find ONE function in it. Apply that function in a 5-line program. The lesson: discoverability is a skill. - Circulate. Common bugs: writing
random.randintafter only doingfrom random import randint(must userandintalone now); forgetting thatfrom datetime import datetimeimports the CLASS, so it'sdatetime.now()notdatetime.datetime.now()(this trips even pros).
🚪 Exit Ticket (5 min)
- On paper: "What's the difference between
import mathandfrom math import sqrt? Show how you'd USE each one." - Looking for:
import math→ use asmath.sqrt(16).from math import sqrt→ use assqrt(16)(no prefix). Both produce 4.0; the import style determines how you call.
⚠️ Watch For — Common Misconceptions
import random at the top, then randint(1, 6) in code. Crashes — randint not defined at module level.import random → use as random.randint(1,6). from random import randint → use as randint(1,6). Don't mix.datetime.datetime.now() is too long, must be wrong."datetime being a module containing a CLASS also called datetime.import datetime; datetime.datetime.now() is correct (long). from datetime import datetime; datetime.now() is shorter. Most code uses the second form. Don't fight the design.math.pi is a function — needs parens."math.pi(). Crashes — pi is a value, not a function.help(math.pi) to find out which. Drill: math.pi = 3.14159..., a constant.random.shuffle returns a shuffled list."x = random.shuffle(my_list). x is None. Confusion.shuffle() mutates the list IN PLACE and returns None. Same mistake pattern as list.sort(). Read the docs (help(random.shuffle)) to know which functions mutate vs return.🎯 Differentiation
For early finishers
Challenge: explorecollections.Counter using help(). Use it to count word frequencies in a paragraph. Stretch: research itertools, pick one function (permutations or combinations), and demo it.
For struggling students
Stay on Lab 6.4A but with just ONE module. Pickrandom. The win: import random and random.randint(1, 6) work correctly in their program. The other forms can be revisited.
💬 Discussion Prompts
- Why does Python ship with so much "standard" stuff? ("Batteries included" — Python's design philosophy. Most common needs (random, math, dates, files, JSON, sockets) are pre-built. Saves everyone from rewriting them.)
- What's a "module" really? (Just a .py file.
import mathfindsmath.pyin Python's library and loads it. You'll see in Lesson 5 — your own .py files work the exact same way.) - If pros don't memorize the standard library, what DO they memorize? (The names of common modules and the GENERAL idea of what each does. They remember "random has shuffle, choice, randint" — and look up the exact signatures with
help()or docs.)
🌍 Real-World Connections
- Every Python project on GitHub. Open any project. The top of every file: imports. The standard library is the foundation under everything.
- Pip and PyPI. Beyond the standard library, Python has 400,000+ third-party modules on PyPI.
pip install requestsand you can talk to any web API. (Preview Unit 8.) - Data science. NumPy, Pandas, Matplotlib — all third-party modules. Master
importin Unit 6 and you've unlocked the entire data-science Python ecosystem. - Reading other people's code. Every code review, every Stack Overflow answer, every tutorial uses imports. Reading them = the gateway to understanding modern Python.
📖 Lesson-Specific Vocabulary
from x import y grabs ONE tool. as renames locally.📇 Lesson 5 · Custom Modules + Persistent Contact Vault
Lesson 5 · Custom Modules + Persistent Contact Vault
Project PlanAt-a-Glance
.py file is a module, split a project across two files (UI + helpers), use the if __name__ == "__main__": guard correctly, and integrate every Unit 6 skill into the Persistent Contact Vault — a two-file app whose data survives between runs.__main__, Two-File Architecturecontact_vault.py + vault_io.py) is the single most professionally valuable concept in the course. Don't compress. Day 1 covers custom modules + Plan + Code stages. Day 2 covers Test + Fix + Maintain + Showcase. The 2-day pacing is non-negotiable.
Project Flow (90+ min across 2 days)
📅 Day 1 — Custom Modules + Plan + Code (45–55 min)
- Warm-up (5 min): Project the Unit 5 Contact Vault. Run it. Add 3 contacts. Quit. Restart. Vault is empty. Ask: "What's missing?" Answer: persistence. Today's project: give the vault a memory.
- Custom Modules (15 min): Walk through Lesson 6.5 Sections 1–3. The big reveal: any
.pyfile is a module. Live-demo: writegreetings.pywith two functions; writemain.pythat imports and uses it. Two files, one program. - The
if __name__ == "__main__":guard. Why: when a file is RUN directly, Python sets__name__to"__main__". When a file is IMPORTED,__name__equals the module name. The guard means "only run main() when this file is executed directly — not when it's imported." Drill this. Most students don't get it the first time. - Capstone introduction (10 min): Project the two-file architecture diagram:
contact_vault.py vault_io.py ───────────────── ───────────────── import vault_io import json, os, datetime vault = [] def add_contact(): def load_vault(filename): def remove_contact(): try/except → list def search_contacts(): def list_contacts(): def save_vault(vault, filename): def main(): json.dump(...) if __name__ == "__main__": main() def now_string(): datetime.now().strftime(...) - Two files. Two responsibilities. Main file = UI/menu/state. Helper file = disk/timestamp work. The capstone rubric is built around this split.
- SDLC Stage 1 — Plan (5 min): Distribute paper. Students answer 4 questions: (1) Which functions go in which file? (2) What's the data shape — including the new
created_atfield? (3) What 2 exceptions doesload_vaultneed to catch? (4) Where does the guard go and why? Stage 1 deliverable. - SDLC Stage 2 — Code (15–20 min): Students build
vault_io.pyFIRST (helper module). It's smaller and more focused. Then they wirecontact_vault.pyto use it viaimport vault_io. The order matters — students who try to build the main file first usually get tangled.
📅 Day 2 — Test + Fix + Maintain + Showcase (45 min)
- SDLC Stage 3 — Test (15 min): Students apply edge-case testing. The unit's signature test: corrupt-file recovery. Students CORRUPT
contacts.jsonby hand (delete a brace, add garbage), then restart. App should NOT crash — should start fresh. This is the rubric's hardest test, worth 15 of 100 points. - Other tests: persistence across restart (most important — 20 of 100), missing file recovery, empty vault listing, weird input characters. Document a test-case worksheet at the bottom of
contact_vault.py. - SDLC Stage 4 — Fix (10 min): Apply the 4-step debugging strategy. Pair-test where time allows. Common Day 2 bugs: forgetting to call
save_vaultafter add/remove (state lives in memory but never persists); using"w"when meant"a"on accidental file work; importing the WHOLE menu when they only meant to import helpers (the guard fixes this). - SDLC Stage 5 — Maintain (10 min): Polish for long-term. Header comment block, docstrings on every function in BOTH files, organized imports, version notes at bottom. Ensure the helper module imports cleanly without running the menu (the guard test).
- Showcase & Submit (10 min): Pick 3–5 volunteers. Run their app, add a contact, quit, restart, see the contact STILL THERE. The audible "ohh" is the unit's emotional payoff. Project the two-file architecture briefly. Note: different students will have organized helpers differently — that's standard 05.06 (multiple algorithms) made visible.
⚠️ Watch For — Common Project Pitfalls
save_vault after add/remove."add_contact, remove_contact) should END with vault_io.save_vault(vault, "contacts.json"). Without that line, the vault lives in memory only. Drill: "every change writes to disk."import vault_io at top, then save_vault(...) in code. NameError.import vault_io, all helper functions need the vault_io. prefix. Either keep the prefix (preferred — explicit) OR change to from vault_io import save_vault, load_vault, now_string (then no prefix). Don't mix.__main__ guard."main() would run when the file is imported elsewhere. With our 2-file setup, it might not be obvious until students run a test. Stage 5 deduction.if __name__ == "__main__": main(). Worth 10 of 100 rubric points; not optional.except FileNotFoundError works for first run. Hand-edit corrupts the JSON. Restart. JSONDecodeError crashes the app.except (FileNotFoundError, json.JSONDecodeError):. The tuple syntax. Test it the way the rubric does: hand-corrupt the file, then restart. App must start fresh, not crash. 15 of 100 rubric points.contact["location"][0] still works (it does — but it's now a list, not a tuple).created_at field.""created_at": vault_io.now_string(). Goes in add_contact() when building the dict. The rubric checks for it (10 of 100 points).🎯 Differentiation
For students who finish early
Direct them to stretch goals from the lesson: alphabetical sort (vault.sort(key=lambda c: c["name"].lower())), filter by date added, random pick (random.choice(vault)), pretty phone format on display, dedup on add. Each adds +5 pts (max +20).
For struggling students
It's OK if their version has only ONE save point (after add) instead of saving on every operation. They still demonstrate persistence. The win: contacts survive a restart. The corrupt-file recovery test can be revisited.💬 Discussion Prompts
- Why split into two files? Couldn't this all be in one file? (Yes — but: 1) The helper module is reusable in OTHER projects. 2) Each file is shorter and easier to read. 3) Code reviews are easier — different reviewers can look at UI vs I/O independently. 4) Bugs are easier to isolate — if persistence breaks, you know to look in vault_io.py. The split is the SAME modular thinking from Unit 4 functions, but at the file level.)
- What does the
__main__guard actually protect against? (Without it, importing the file would RUN the menu loop. Imagine ifimport vault_iolaunched a menu — would be chaos. The guard ensures only DIRECT execution runs main.) - The Persistent Contact Vault has the same data shape as a real CRM. What ELSE would a real CRM add? (User accounts, sync across devices, search by phone/email/etc, contact history, notes per contact, encryption. This capstone is the SKELETON; production CRMs are this PLUS dozens of features. But the bones are these bones.)
🌍 Real-World Connections
- Every desktop app on the planet. Save game files. Document files. Browser bookmarks. Settings. They all use the same pattern: load on startup, save on change, recover from corruption. The Persistent Contact Vault is a tiny version of every desktop app's persistence layer.
- Two-file architecture is everywhere. React: components.jsx + utils.js. Django: views.py + models.py. Express: routes.js + db.js. Real apps split UI from data. Unit 6 is the entry point.
- NoSQL databases. The capstone's
contacts.jsonfile IS a tiny JSON-document database. MongoDB, Firebase, CouchDB — they're this pattern at scale, with networking and concurrency added. Master the simple version first. - Resume bullet point. "Built a multi-file Python application with JSON persistence, exception handling, and timestamped records." Not a stretch — that's literally what students did.
📋 Persistent Contact Vault Project Rubric (100 points)
The rubric matches the one in the student lesson exactly. Share with students at the start of Day 1.
| Category | What to look for | Pts |
|---|---|---|
| Two-File Architecture | Code split into contact_vault.py + vault_io.py. Main file imports the helper module and uses it via prefix. | 15 |
| Persistence Works | Contacts survive program restart. Adds and removes are saved immediately. JSON file on disk reflects current state. | 20 |
| Error Handling | Both FileNotFoundError AND json.JSONDecodeError are caught. App starts fresh on either, doesn't crash. | 15 |
| Timestamps | Each contact has a created_at field set via datetime.strftime. Visible in JSON and when listing. | 10 |
Use of __main__ | contact_vault.py has a guarded main() call. Helper module imports cleanly without running the menu. | 10 |
| String Cleanup | Inputs cleaned (strip, lower, replace) — same standard as Unit 5 capstone. | 10 |
| Clean Code Style | snake_case, 4-space indent, docstrings on every function, organized imports, no bare except. | 10 |
| Works Correctly | All 9 test cases from Stage 3 pass. Especially: persistence across restart and corrupt-file recovery. | 10 |
| TOTAL | 100 | |
🎁 Stretch Goals (extra credit)
- Alphabetical sort with
sorted(... key=lambda): +5 pts - "Show contacts added today" filter using
created_at.startswith(today): +5 pts - Random pick —
random.choice(vault)for "who should I call?": +5 pts - Pretty phone format on display via slicing: +5 pts
- Duplicate detection on add (case-insensitive name match): +5 pts
Maximum stretch credit: +20 points. Document each stretch in version notes at the bottom of contact_vault.py.
📖 Lesson-Specific Vocabulary
.py file YOU wrote that another file imports."__main__" when a file is run directly. Used by the guard.🛠️ Appendix · Common Python Errors in Unit 6
This appendix lists the most common Python error messages students will see in Unit 6. File and module work introduces a new family of errors — FileNotFoundError, PermissionError, json.JSONDecodeError, ModuleNotFoundError, plus the silent bugs of forgetting with, using "w" when meant "a", and circular imports. Apply Unit 4's 4-step strategy: Reproduce → Read → Hypothesize → Fix & Verify, ONE change at a time.
What it usually means: Tried to read a file that doesn't exist yet. Common on first run.
How to fix: Wrap in try/except FileNotFoundError and start fresh on miss. The capstone tests this explicitly. Or check os.path.exists() before opening — but try/except is cleaner.
What it usually means: The file isn't valid JSON. Either empty, or a human edited it badly (missing brace, unquoted key, trailing comma).
How to fix: Catch json.JSONDecodeError alongside FileNotFoundError: except (FileNotFoundError, json.JSONDecodeError):. App starts fresh. The capstone's signature test.
What it usually means: The file exists but the OS won't let Python read or write it. On school computers, this happens when files are owned by another user.
How to fix: Save in a writable directory (your home folder or the project folder, not /etc or C:\Windows). Use a relative path like "contacts.json" and let the file land in the current working directory.
What it usually means: Most Python types serialize to JSON. Tuples actually do (they become lists). But custom classes (Unit 7) don't, and neither do sets or datetimes by default.
How to fix: Convert to JSON-friendly types BEFORE saving. set → list(my_set). datetime → dt.strftime("%Y-%m-%d %H:%M"). The capstone uses the second pattern for created_at.
What it usually means: Your vault_io.py file isn't in the same folder as contact_vault.py. Or the filename has a typo.
How to fix: Both files in the same folder. Filenames match the import statement EXACTLY (case-sensitive on Mac/Linux). import vault_io means the file is vault_io.py.
What it usually means: Typo in a function name. Common with randint (the "i" before "n").
How to fix: Spell it correctly: random.randint. Use dir(random) if unsure — it lists everything available.
"w" mode wiped the file)What it usually means: Used "w" when meant "a". The file is now empty (or just contains the latest write).
How to fix: Use "a" for append. Use "w" ONLY when intentionally replacing the entire file. Drill the safety: "w" = wipe.
What it usually means: File was opened without with and never explicitly closed. Buffered writes never flushed to disk.
How to fix: Always use with open(...) as f:. Auto-closes; auto-flushes. Avoids this entire class of bug.
What it usually means: File A imports B, B imports A. Python tries to load both at once, hangs or partially loads, mysterious AttributeError later.
How to fix: Restructure so dependencies go ONE WAY. In the capstone: contact_vault.py imports vault_io.py; vault_io.py imports nothing project-local. The helper file shouldn't know about the UI.
Watch list — these still happen in Unit 6 capstones:
KeyErrorin nested dict access — use.get()or guard withif key in d.- Mutating a list during iteration — find indices first, then delete.
- Functions returning
None—printinstead ofreturn. Echo of Unit 4. - Forgetting to
.strip()input — leading/trailing whitespace breaks search and dedup. - Indentation errors when functions, loops, and try/except all nest deeply.
os.path.exists(filename). (B) "What does the file actually contain?" Open it in a text editor. Most Unit 6 bugs are FILE-SHAPE bugs — the file exists but doesn't contain what the code assumes. Once you can see the file's actual contents, the fix is usually obvious.
— End of Unit 6 Teacher's Guide —
