Week 12 — Lecture Outline · File I/O & Exceptions
Course: Introduction to Computer Science — CS1 / Programming Fundamentals in Python (CSCI 1101) · Silver Oak University (fictional sample) · Prof. Okafor
Objective covered: Objective 7 — Process strings and files, and handle errors using try / except.
SLOs touched: A (write & run a correct program) · B (trace behavior; find & fix a defect)
Meeting pattern: 2 studio sessions × 75 min = 150 min.
Every code output and error message in this outline was produced by actually running the code in Python — not hand-traced. Run them live; the outputs are exact.
Week at a Glance
| The week's big question | "How does a program remember data between runs — and keep running when something goes wrong?" |
| By the end of the week, students can… | (1) read and write files with with open(...); (2) handle exceptions with try/except and predict which block runs; (3) name the common exceptions (FileNotFoundError, ValueError, ZeroDivisionError, KeyError) and their causes; (4) debug an unhandled exception by reading its type and wrapping the risky line. |
| Key vocabulary | file, open(), mode ("r", "w"), with (context manager), .read(), .readline(), .readlines(), .write(), line iteration, exception, try, except, FileNotFoundError, ValueError, ZeroDivisionError, KeyError, traceback |
| Materials | slides (Deck 12), readings, the online Python editor + Python Tutor, one approved chatbot |
| Timing note | 8 segments, ~150 min. Session 1 = Segments 1–4. Session 2 = Segments 5–8. Studio format — students type and run every example. |
Segment 1 — Hook & the Promise (8 min) · Session 1 opens
Hook. "Write a program that counts how many times you've run it." The room realizes: they can't — every variable resets to zero each run. A program has no memory of yesterday. Files are how programs remember. Then: "Now open a file that doesn't exist." Crash. "Today we also make crashes into polite messages."
The promise: "By Friday your programs can save data to a file, read it back next time, and survive a missing file without crashing."
Memory hook: "with opens it and closes it for you; try the risky line, except catches the fall."
Segment 2 — Reading & Writing Files with with (24 min) · the code-along
Plain language first. A file is data stored on disk that outlives your program. To use one you open it, do your reading or writing, then close it. Python's with block does the closing for you automatically — that's why we always use it.
Code-along, step by step (everyone types and runs):
Write a file:
with open("notes.txt", "w") as f:
f.write("hello\nworld")
"w" means write mode (it creates the file, or overwrites it). \n is a newline. Nothing prints — but a file now exists.
Read it back:
with open("notes.txt") as f:
print(f.read())
Output (run-verified):
hello
world
".read() returns the whole file as one string. The default mode is read, so we don't pass "w"."
Read line by line — iterate the file object:
with open("notes.txt", "w") as f:
f.write("x\ny\nz")
with open("notes.txt") as f:
for line in f:
print(line.strip())
Output (run-verified):
x
y
z
".strip() removes the trailing newline on each line. for line in f: is the cleanest way to read a file top to bottom."
Land the key idea: always use with. Outside a with block you'd have to remember f.close(), and forgetting it can lose data. with guarantees the file is closed even if something goes wrong.
Segment 3 — When Things Go Wrong: try / except (22 min)
Plain language first. Some operations can fail at runtime — opening a missing file, converting "abc" to an int, dividing by zero. Without protection, the program crashes with a traceback. try / except lets you say: try this risky thing; if a specific error happens, do this instead.
Worked example — a missing file (run it live):
try:
with open("missing.txt") as f:
print(f.read())
except FileNotFoundError:
print("Sorry, that file was not found.")
Output (run-verified):
Sorry, that file was not found.
"Python tried the try block, hit a FileNotFoundError, and jumped to the matching except. No crash — just a friendly message."
Worked example — a bad conversion:
try:
n = int("abc")
print(n)
except ValueError:
print("That was not a number.")
Output (run-verified):
That was not a number.
Which block runs? (predict, then run): if the try block succeeds, the except is skipped:
try:
x = 5 / 1
print("ok:", x)
except ZeroDivisionError:
print("div0")
Output (run-verified):
ok: 5.0
"No error → the except never runs. (And notice 5 / 1 is 5.0 — division always gives a float.)"
Segment 4 — The Common Exceptions (18 min) · Session 1 closes
Name them and what triggers each (run each to see the real traceback's last line):
| Exception | Triggered by | Last line (run-verified) |
|---|---|---|
FileNotFoundError |
opening a file that isn't there | FileNotFoundError: [Errno 2] No such file or directory: 'missing.txt' |
ValueError |
converting bad text, e.g. int("3.5") |
ValueError: invalid literal for int() with base 10: '3.5' |
ZeroDivisionError |
dividing by zero, 10 / 0 |
ZeroDivisionError: division by zero |
KeyError |
a missing dictionary key, d["b"] |
KeyError: 'b' |
Quick interaction (rapid-fire): name the exception each line raises — open("nope.txt") → FileNotFoundError; int("ten") → ValueError; 7/0 → ZeroDivisionError; {"a":1}["z"] → KeyError. (Run any that the room argues about.)
Segment 5 — Spot & Fix the Bug (the debugging demo) (20 min) · Session 2 opens
The buggy program (it crashes on a missing file):
filename = "scores.txt"
with open(filename) as f:
print(f.read())
Debug it together: if scores.txt doesn't exist, run-verified this raises FileNotFoundError: [Errno 2] No such file or directory: 'scores.txt' and the program stops. The fix — wrap it so a missing file is handled:
filename = "scores.txt"
try:
with open(filename) as f:
print(f.read())
except FileNotFoundError:
print("No scores file yet — starting fresh.")
Now a missing file prints a friendly message instead of crashing (run-verified).
Land the key idea: debugging an exception is a loop: run it → read the exception type on the last line → wrap the risky line in try/except for that type → run again.
Segment 6 — A Useful Pattern: Save-and-Reload (18 min)
Build a tiny "memory" program (code-along): write a list of items to a file, then read them back and count.
fruits = ["apple", "banana", "cherry"]
with open("fruit.txt", "w") as f:
for fruit in fruits:
f.write(fruit + "\n")
with open("fruit.txt") as f:
count = 0
for line in f:
count += 1
print("Lines:", count)
Output (run-verified):
Lines: 3
"We wrote three lines, then read them back and counted them — the program 'remembered' across the two halves. Run it twice and the file persists between runs."
Misconception + cure:
- ❌ ".read() gives me a number if the file holds 42."
✅ Cure: a file read is always a string. with open("n.txt") as f: print(type(f.read())) → run-verified <class 'str'>. Convert with int(...) (and wrap that in try/except ValueError).
Segment 7 — Misconceptions Round-Up + Interaction (20 min)
Name the misconceptions, then cure each:
- ❌ "I have to close the file myself." ✅ Not with with — it closes automatically.
- ❌ ""w" adds to the file." ✅ "w" overwrites (creates fresh). (Appending uses "a" — a preview, not required this week.)
- ❌ "try/except catches everything." ✅ It catches the type you name. except ValueError won't catch a FileNotFoundError.
- ❌ "A file read gives me numbers." ✅ It gives strings; convert as needed.
Interaction — predict-then-run (rapid-fire): put 3 short try/except programs on a slide; students predict which block runs and what prints; you run all three.
Segment 8 — Technology Workflow + AI-Critique, Callback & Hand-off (20 min) · Session 2 closes
Technology workflow: (1) write with with open(name, "w"); (2) read with with open(name); (3) wrap anything that can fail in try/except <SpecificError>; (4) read the exception type on the last line of a traceback to know which except to add.
AI-critique moment:
Ask a chatbot: "Write a program that reads a file and handles the case where it doesn't exist." Then check it by running it: did it catch
FileNotFoundErrorspecifically, or use a bareexcept:that hides every bug? Did it actually create/read the file correctly? Chatbots often catch the wrong exception type or use a too-broadexcept. The tool drafts; you run it and judge.
Callback + tease:
- Callback: "Files give your programs memory; try/except gives them resilience."
- Tease next week: "We have data in files and collections. Next week we ask: how do we search and sort it efficiently — linear vs. binary search — and we'll start counting steps with Big-O."
Hand-off: Lecture Tutorial 12; Quiz 12; Discussion 12 ("Fail Loudly or Fail Silently?"); Assignment 12 ("Remember & Recover"); Coding Lab 12 — "Save, Read, Recover."
Instructor FAQ — Common Stumbles
| Student says / does | Quick cure |
|---|---|
Forgets with, leaves files open. |
Always use with open(...) as f: — it closes for you. |
Expects "w" to append. |
"w" overwrites; the file starts empty. |
except ValueError doesn't catch a missing file. |
Catch the right type — FileNotFoundError for a missing file. |
Treats f.read() as a number. |
A read returns a string; wrap int(...) in try/except ValueError. |
Uses a bare except:. |
Catch a specific exception so real bugs aren't hidden (see this week's discussion). |
| Panics at a traceback. | Read the last line: it names the exception type and the cause. |
Scope flag
This outline stays within Objective 7's files-and-exceptions half: with open reading/writing, try/except, and the four common exceptions. Append mode "a", reading/writing CSV/JSON, custom exceptions, finally/else clauses, and raise are beyond CS1's first pass and noted only in passing. Python's exception names are referenced factually; the instructor and institution remain fictional. Every output shown was produced by running the code.
~ Prof. Okafor's edition · Fall 2026 · built with thecoursemaker.com