Reading and writing files

INPUT · Slides

Write it, then read it back

01 / 07

One trip outside your program

Take some text out of a variable, put it into a file, and bring it back into a variable.

It is a small thing, but you have just made one trip outside your program. An ordinary variable disappears the moment the run ends; what you put in a file stays. That difference is the decisive one.

memo = "buy milk"with open("memo.txt", "w") as f:    f.write(memo)with open("memo.txt") as f:    loaded = f.read()print(loaded)

Result

buy milk

02 / 07

What comes back is always text

Write a number and what you read back is text, because text is the only thing a file can hold.

So if you want to do sums with it, you have to put it through int(). The converting between kinds you did in Chapter 1 comes into its own here.

with open("number.txt", "w") as f:    f.write("300")with open("number.txt") as f:    text = f.read()print("$" + text)print(int(text) + 100)

Result

$300
400

03 / 07

Write and read to the same rule

When you want to keep a list, settle on a rule — one item per line, say. You join it up with join to write, and split it apart with splitlines to read.

What matters is that the two face the same rule. Change the writing side to commas on its own and the reading side breaks.

fruits = ["apple", "orange", "grape"]with open("fruit.txt", "w") as f:    f.write("\n".join(fruits))with open("fruit.txt") as f:    loaded = f.read().splitlines()print(loaded)

Result

['apple', 'orange', 'grape']

04 / 07

json turns a dictionary into text

Hand a dictionary straight to write and you get a TypeError. Text was the only thing it takes.

This is where json from Chapter 6 comes back in. json.dumps turns a dictionary into text as it stands.

By default, any character outside plain ASCII is swapped for an escape like \u00e9. Pass ensure_ascii=False and the characters come out as themselves, so that is the form we use from here.

import jsonmenu = {"café": 250, "crème": 600}print(json.dumps(menu))print(json.dumps(menu, ensure_ascii=False))

Result

{"caf\u00e9": 250, "cr\u00e8me": 600}
{"café": 250, "crème": 600}

05 / 07

Save a dictionary and get a dictionary back

Turn it into text with json.dumps on the way out, and back into a dictionary with json.loads on the way in. The dictionary has made the round trip still a dictionary.

What comes back behaves exactly like any other dictionary. You can look things up by key and loop over it with for.

A budget tracker, a game save, an application settings file — underneath, this is the shape they are all kept in.

import jsonstock = {"apple": 3, "orange": 5}with open("stock.json", "w") as f:    f.write(json.dumps(stock, ensure_ascii=False))with open("stock.json") as f:    loaded = json.loads(f.read())print(loaded)print(loaded["apple"])

Result

{'apple': 3, 'orange': 5}
3

06 / 07

Be ready for a file that is not there yet

It happens often enough that the file you saved to is not there. The very first run, for one.

Try to read a missing file and FileNotFoundError stops you. This is where try and except from Chapter 4 come in. Write if it is not there, start from a default and your program survives its own first run.

try:    with open("no-save.txt") as f:        content = f.read()except FileNotFoundError:    content = "nice to meet you"print(content)

Result

nice to meet you

07 / 07

What this chapter has given you

Open a file, read it, write it, read it back. You can now leave data outside your program and fetch it out again.

  • a notes app … keep what was written, and show it next time round
  • a budget tracker … pile up what was spent, and total it
  • a game save … keep how far you got, and carry on from there

They look nothing alike, but the root of every one of them is this round trip.

In the next chapter we go and find out why for worked the same way on a list, on a string and on a file.