Reading and writing files

INPUT · Slides

Reading a line at a time

01 / 07

The whole thing at once is awkward

read gives you the contents as one single string. Fine for a short note, but awkward the moment you want to do something per line.

"Add up every line with a score on it." "Show only the lines of three characters or more." What you want there is a way to take one line at a time.

02 / 07

A file loops with for

The way to do it is almost disappointingly simple. Just write for line in f:. Exactly the same shape as looping over a list.

One thing to watch, though. Each line comes to you with its newline still attached. So print gives you blank lines in between.

with open("memo.txt", "w") as f:    f.write("morning\nnoon\nnight\n")with open("memo.txt") as f:    for line in f:        print(line)

Result

morning

noon

night

03 / 07

Drop the newline with strip

Take the strip from the last lesson and apply it to each line. Write line.strip() and that is it.

When you loop over a file with for, you write the strip alongside it. The pairing is common enough that you may as well learn it that way.

with open("memo.txt", "w") as f:    f.write("morning\nnoon\nnight\n")with open("memo.txt") as f:    for line in f:        print(line.strip())

Result

morning
noon
night

04 / 07

Chapter 2's for worked unchanged

Put the code you have just written next to the code that loops over a list. Only what follows in is different — nothing else has moved.

That is not an accident. Lists, strings, dictionaries, files: Python is designed so the same for loops over all of them.

Things you can loop over share a common agreement, and for runs on that agreement alone. Chapter 8 gives away what it is. For now it is enough to notice that the same writing keeps working everywhere.

fruits = ["apple", "orange"]for fruit in fruits:    print(fruit)with open("memo.txt", "w") as f:    f.write("apple\norange\n")with open("memo.txt") as f:    for line in f:        print(line.strip())

Result

apple
orange
apple
orange

05 / 07

readlines makes a list

The other way to read is readlines, which hands back every line as a list.

Being a list, you can count it with len or take the first line with [0]. The newlines are still there, though, so you want a strip before you show anything.

with open("memo.txt", "w") as f:    f.write("morning\nnoon\nnight\n")with open("memo.txt") as f:    lines = f.readlines()print(lines)print(len(lines))

Result

['morning\n', 'noon\n', 'night\n']
3

06 / 07

Choosing between for and readlines

Pick between the two like this.

  • for line in f: … read a line, deal with it, read the next. Light on however large a file
  • f.readlines() … load every line into a list at once. For counting the lines, or looking back at them repeatedly

When in doubt, use for. Read a file of several million lines with readlines and every one of them lands in memory.

with open("memo.txt", "w") as f:    f.write("morning\nnoon\nnight\n")with open("memo.txt") as f:    lines = f.readlines()print(f"{len(lines)} lines")

Result

3 lines

07 / 07

Summary

There were two ways to read a line at a time.

  • loop with for line in f: and drop the newline with line.strip()
  • make a list with f.readlines()

And one more thing worth noticing. The for you learned in Chapter 2 worked on a file unchanged. Hold on to that feeling of "the same writing keeps working".

That covers reading. In the next group we take writing seriously: the difference between "w" and "a", and how people accidentally empty a file that mattered.