Python Series track

Week 06 · Intermediate Track

Week 6 — File I/O

Persist data to disk with Python's file I/O. Read and write plain text, CSV, and JSON files using context managers, the csv module, and json module.

Intermediate Track2 min readFree lesson

Level: Intermediate | Prerequisite: Week 5 (Exception Handling)

Learning Goals

  • Handle text files safely with with open
  • Read and write CSV files using the csv module
  • Save and load structured data in JSON

1. Text Files

with Statement (Recommended)

Automatically closes the file.

#Write
with open("notes.txt", "w", encoding="utf-8") as f:
    f.write("First line")
    f.writelines(["A\n", "B\n", "C\n"])

#Read
with open("notes.txt", encoding="utf-8") as f:
    content = f.read()      #All at once
    #Or
    for line in f:           #One line at a time
        print(line.rstrip())

Modes

Mode Meaning
r Read (default)
w Write (overwrite existing content)
a Append
r+ Read/Write
b Binary (e.g., rb, wb)

⚠️ Always specify encoding="utf-8" (safe for Korean).

2. CSV

Comma-separated table format.

import csv

#Write
with open("scores.csv", "w", encoding="utf-8", newline="") as f:
    w = csv.writer(f)
    w.writerow(["name", "score"])
    w.writerows([["Alice", 92], ["Bob", 78]])

#Read
with open("scores.csv", encoding="utf-8") as f:
    for row in csv.DictReader(f):
        print(row["name"], row["score"])

⚠️ Missing newline="" causes blank lines (Windows).

3. JSON

Serialize structured data to text.

import json

data = {
    "name": "Hong Gil-dong",
    "skills": ["Python", "SQL"],
    "active": True,
}

#Save
with open("profile.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)

#Load
with open("profile.json", encoding="utf-8") as f:
    loaded = json.load(f)
print(loaded["skills"])

Options:

  • ensure_ascii=False — Keep Korean characters as is
  • indent=2 — Indent for human readability

Key Examples (examples/)

File Content
01_text.py Text File Read/Write
02_csv_write.py Write CSV
03_csv_read.py Read CSV (DictReader)
04_json.py JSON dump/load

⚠️ Common Mistakes

  1. Omitting close after open — Automatically handled by using with.
  2. encoding missing — Korean characters break on Windows.
  3. json.dump vs json.dumps — dump is for files, dumps is for strings.
  4. CSV newline="" missing — Empty lines are added on Windows.
  5. Types that cannot be saved as JSON — datetime, user-defined classes. Conversion is needed.

❓ FAQ

Q1. Which should you use, CSV or JSON? A. Tabular data uses CSV, nested/structured data uses JSON.

Q2. Can I read large files all at once? A. They are loaded into memory, so GB-sized files are risky. Iterate line by line or use generators.

Q3. What is pickle? A. Stores the Python object as it is. However, it cannot be read in other languages and poses a security risk. JSON is recommended.

📝 Exercises (exercises/)

  • exercise1.md — Notepad (text addition)
  • exercise2.md — CSV score statistics
  • exercise3.md — Permanent To-Do JSON storage

Next Week

Week 7. Object-Oriented (1)

Example files

The runnable files used in this lesson. Copy them into your own project and experiment.

examples/01_text.pyPython
#Write
with open("notes.txt", "w", encoding="utf-8") as f:
    f.write("First line")
    f.write("Second line")
    f.writelines(["A\n", "B\n", "C\n"])

#Read — all
with open("notes.txt", encoding="utf-8") as f:
    print(f.read())

print("---")

#Read — line by line
with open("notes.txt", encoding="utf-8") as f:
    for line in f:
        print(repr(line.rstrip()))

#Append mode
with open("notes.txt", "a", encoding="utf-8") as f:
    f.write("Appended line")

import os
os.remove("notes.txt")
examples/02_csv_write.pyPython
import csv

with open("scores.csv", "w", encoding="utf-8", newline="") as f:
    writer = csv.writer(f)
    writer.writerow(["name", "score", "dept"])
    writer.writerows([
        ["Alice", 92, "A"],
        ["Bob", 78, "B"],
        ["Charlie", 85, "A"],
    ])

print("scores.csv created")

#More clearly with DictWriter
with open("scores2.csv", "w", encoding="utf-8", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=["name", "score"])
    writer.writeheader()
    writer.writerow({"name": "Alice", "score": 92})
    writer.writerow({"name": "Bob", "score": 78})

print("scores2.csv created")
examples/03_csv_read.pyPython
import csv

#Read the file created with the above example
with open("scores.csv", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(row)
        print(f"{row['name']}: {row['score']} points ({row['dept']} class)")

#Organize
import os
for fn in ("scores.csv", "scores2.csv"):
    if os.path.exists(fn):
        os.remove(fn)
examples/04_json.pyPython
import json

data = {
    "name": "Hong Gil-dong",
    "age": 20,
    "skills": ["Python", "SQL", "Git"],
    "active": True,
    "address": {"city": "Seoul", "zip": "12345"},
}

#Save
with open("profile.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)

#Load
with open("profile.json", encoding="utf-8") as f:
    loaded = json.load(f)

print(loaded["name"])
print(loaded["skills"])
print(loaded["address"]["city"])

#Directly as a string
s = json.dumps(data, ensure_ascii=False)
print(s[:50], "...")

import os
os.remove("profile.json")

Assignment

Goal

Take notes in a text file using Add/View CLI.

Commands

  • add — Enter note → append to the end of the file
  • show — Print all contents
  • clear — Clear the file
  • quit

Requirements

  • File: notes.txt
  • When adding, format as [YYYY-MM-DD HH:MM] Memo content

Task 2. CSV Score Statistics

Goal

Read students.csv and print Average/Maximum/Minimum scores.

Input File Format

name,score
Alice,92
Bob,78
Charlie,85

Output Example

Number of students: 3
Average: 85.00
Highest: Alice (92)
Lowest: Bob (78)

Task 3. To-Do JSON Persistent Storage

Goal

Add JSON storage to the Week 10 basic To-Do List program.

Requirements

  • Load if todos.json exists at start
  • Save after every change (or once at exit)
  • Keep data even after restarting

Data Structure

[
  {"task": "Buy milk", "done": false},
  {"task": "Read a book", "done": true}
]
Show the reference solution

Try the assignment yourself first — comparing your attempt with a working solution is where most of the learning happens.

solution1.pyPython
from datetime import datetime
from pathlib import Path

NOTES = Path("notes.txt")

while True:
    cmd = input("Command (add/show/clear/quit):").strip()
    if cmd == "quit":
        break
    elif cmd == "add":
        memo = input("Memo:")
        ts = datetime.now().strftime("%Y-%m-%d %H:%M")
        with NOTES.open("a", encoding="utf-8") as f:
            f.write(f"[{ts}] {memo}\n")
        print("Added")
    elif cmd == "show":
        if NOTES.exists():
            print(NOTES.read_text(encoding="utf-8"))
        else:
            print("(No memo)")
    elif cmd == "clear":
        NOTES.write_text("", encoding="utf-8")
        print("Cleared")
solution2.pyPython
import csv
from pathlib import Path

#Create demo input file
Path("students.csv").write_text(
    "name,score\nAlice,92\nBob,78\nCharlie,85\nDave,67\n",
    encoding="utf-8"
)

with open("students.csv", encoding="utf-8") as f:
    rows = list(csv.DictReader(f))

scores = [(r["name"], int(r["score"])) for r in rows]
total = sum(s for _, s in scores)
avg = total / len(scores)
top = max(scores, key=lambda x: x[1])
bot = min(scores, key=lambda x: x[1])

print(f"Number of students: {len(scores)}")
print(f"Average: {avg:.2f}")
print(f"Highest: {top[0]} ({top[1]})")
print(f"Lowest: {bot[0]} ({bot[1]})")

Path("students.csv").unlink()
solution3.pyPython
import json
from pathlib import Path

DB = Path("todos.json")

def load():
    if DB.exists():
        return json.loads(DB.read_text(encoding="utf-8"))
    return []

def save(todos):
    DB.write_text(json.dumps(todos, ensure_ascii=False, indent=2), encoding="utf-8")

todos = load()
print(f"Loaded {len(todos)} to-dos")

while True:
    cmd = input("Command (add/list/done <n>/quit):").strip()
    if cmd == "quit":
        save(todos)
        break
    if cmd == "add":
        task = input("To-do:")
        todos.append({"task": task, "done": False})
        save(todos)
    elif cmd == "list":
        for i, t in enumerate(todos, 1):
            mark = "[x]" if t["done"] else "[ ]"
            print(f"{i}. {mark} {t['task']}")
    elif cmd.startswith("done "):
        idx = int(cmd.split()[1]) - 1
        if 0 <= idx < len(todos):
            todos[idx]["done"] = True
            save(todos)

Learn this lesson with a mentor

Work through the Python Series track on your own, or join a guided cohort at our Pitampura campus and online.

Call NowEnroll Now