Chapter 4 · Mid-level Developer

Reading and writing files

Sooner or later a program needs to touch the disk — save a config, read a log, append to a record. open(path, mode) gives you a file object; the mode says what you intend to do:

  • 'r'read (the default). Errors if the file doesn't exist.
  • 'w'write. Creates the file, and *wipes it* if it already exists.
  • 'a'append. Creates if needed, adds to the end without erasing.

Always open files inside a with block. with open(...) as f: gives you the file as f for the indented block, then closes it automatically when the block ends — even if an error is thrown partway through. Without with, a forgotten .close() can leave data unwritten or the file locked.

Inside the block: f.write(text) writes a string (it does *not* add a newline — you add '\n' yourself); f.read() returns the whole file as one string; and looping for line in f: gives you the file line by line.

Syntax

with open(path, 'r') as f:   # read
    content = f.read()

with open(path, 'w') as f:   # write (overwrites!)
    f.write('hello\n')

with open(path, 'a') as f:   # append
    f.write('one more\n')

for line in f:               # iterate line by line
    ...

Worked examples

Write lines, then read them back

def write_lines(filepath, lines):
    with open(filepath, 'w') as f:
        for line in lines:
            f.write(line + '\n')

def read_lines(filepath):
    with open(filepath, 'r') as f:
        content = f.read()
    return [l.strip() for l in content.splitlines()]

write_lines('/tmp/notes.txt', ['alpha', 'beta', 'gamma'])
print(read_lines('/tmp/notes.txt'))
# Output:
# ['alpha', 'beta', 'gamma']

Append adds; write wipes

with open('/tmp/log.txt', 'w') as f:
    f.write('first\n')
with open('/tmp/log.txt', 'a') as f:
    f.write('second\n')

with open('/tmp/log.txt') as f:
    print(repr(f.read()))
# Output:
# 'first\nsecond\n'

# Re-opening in 'w' would have erased 'first' first.

Iterate a file line by line (memory-friendly)

with open('/tmp/log.txt') as f:
    for line in f:
        print(line.strip())
# Output:
# first
# second

Common mistakes & gotchas

'w' silently destroys the file

Opening an existing file in 'w' mode wipes its contents the instant you open it — before you write anything. If you mean to add to a file, use 'a'. Reaching for 'w' on a file you care about is a classic data-loss bug.

write() does not add a newline

f.write('alpha') followed by f.write('beta') gives you alphabeta on one line. write() is not print(). Add '\n' yourself when you want separate lines.

Forgetting with leaves files open

Without with, you must call f.close() yourself — and if an exception fires first, you never reach it. Buffered writes may never hit disk and the OS handle leaks. Always prefer with open(...) as f:.

Why it matters

Files are how programs remember things after they stop running. Config, logs, exports, caches — all of it lives on disk. The `with open(...)` pattern is one you'll type thousands of times, and getting the mode right is the difference between saving data and quietly destroying it.