While a program is running, data lives in memory (RAM) inside variables, lists, and dictionaries. When the program ends, that data is cleared. A file, in contrast, stores data on disk and provides persistence, so you can load it later. In class we mainly handle text-based files: plain text (.txt), comma-separated values (.csv) for tables, and JSON (.json) for structured data like lists and dictionaries. In Python, open() returns a file object; using it within a with block ensures the file is automatically closed, preventing resource leaks and guaranteeing that data is flushed to disk.
When opening a file, the mode determines the operation. The mode 'r' opens a file for reading and requires the file to exist. The mode 'w' opens a file for writing and overwrites existing content or creates a new one. The mode 'a' appends new content at the end and also creates the file if it does not exist. To avoid text corruption across platforms and languages, we will explicitly use encoding="utf-8" for reading and writing. File paths also matter: relative paths are interpreted from the current working directory (you can inspect it with os.getcwd()), while absolute paths start at the system root. For classroom demos, it is practical to keep data files in the project folder or a subfolder and prefer relative paths for clarity.
Syntax & Minimal Pattern:
with open("notes.txt", "w", encoding="utf-8") as f:
f.write("Hello, file!n")
# file auto-closed here# Minimal, safe pattern
Notes: with open(...) as f: guarantees auto-close when the block ends; encoding="utf-8" avoids garbled text.
Example A: Write & Read
# write_text.py
with open("hello.txt", "w", encoding="utf-8") as f:
f.write("Line 1n")
f.write("Line 2n")
# read_text.py
with open("hello.txt", "r", encoding="utf-8") as f:
text = f.read() # read whole file
print(text)
with open("hello.txt", "r", encoding="utf-8") as f:
for line in f: # iterate line by line
print("LINE:", line.strip())
Output example A:
Line 1
Line 2
LINE: Line 1
LINE: Line 2
Notes A: f.read() reads everything (good for small files); iterating lines is memory-friendly. strip() removes trailing newline.
The output first shows the entire file, then prints each line with a LINE: prefix. If you want to accumulate messages, switch to append mode and write at the end of a log file, optionally with a timestamp.
Example B: Append with Timestamp
import time
msg = input("Log message: ")
stamp = time.strftime("%Y-%m-%d %H:%M:%S")
with open("app.log", "a", encoding="utf-8") as f:
f.write(f"[{stamp}] {msg}n")
print("Appended to app.log")
Notes B: 'a' adds lines to the end—ideal for simple logging.
Example C: Paths & CWD
import os
print("CWD:", os.getcwd())
with open("data/scores.txt", "w", encoding="utf-8") as f:
f.write("Alice,90n")
Notes C: If you see “file not found,” print os.getcwd() to verify where your relative paths point. Create folders if needed.
A few details commonly cause trouble. Forgetting to close files can leave data unwritten or the file locked; with open(...) solves this by auto-closing. Using 'w' when you intended to keep existing content will truncate the file; choose 'a' to add to the end. Encoding mismatches lead to garbled text; explicitly setting encoding="utf-8" is a reliable classroom default. Finally, path confusion is frequent because a relative path is resolved against the current working directory rather than the script’s folder; if you see “file not found,” print os.getcwd() and verify the path you are using.
Now that you know what files are and how to read/write them, we’ll make data more structured: first with CSV for tables, then JSON for lists and dictionaries—making data cleaner and more portable.