← Back to the Introduction to Computer Science outline The Course Maker
← Introduction to Computer Science outline
Week 12 · Chapter

Chapter 12 — File Input/Output & Exceptions

Introduction to Computer Science Free sample edition

The module's primary reading · ~40–50 minutes · Objective 7 (process text with string methods, read and write files with the with statement, and handle runtime errors with try and except by exception type) and Objective 1 (explain what a program and an algorithm are and how a Python program runs, write and run short programs, trace them line by line to predict their output, and read an error message to tell a syntax error from a runtime exception) · Read it first this week; the lecture, the slides, the tutorial, the quiz, and the Coding Lab all build on it.


In plain language

Every program you have written so far forgets everything the moment it stops. This week you give a program a memory: a file (a named store of text on your computer's disk that keeps its contents after the program ends), which one run can write and the next run can read back. You also learn what to do when something goes wrong while a program runs. Python reports each problem as an exception (a signal that names the kind of problem, such as a missing file or text that is not a number), and you can catch the ones you expect so the program keeps going. As always, you predict what each program prints and then run it to check.

Why you already care about this

Picture an illustrative fitness tracker that counts 4,200 steps one day, 6,800 the next, and 5,100 the day after. When you open the app on the fourth morning, those three numbers are still there, even though the phone was switched off twice in between. Somewhere the app wrote them down, and it read them back when it started. That is a file at work.

The same app also has to cope with bad data. Say a sync glitch saves "n/a" instead of a step count. A careless program would crash on that one line and show you nothing. A careful one skips the bad line, adds up the other 2 days, and tells you what it skipped.

Your reading log has the same two needs. Since Week 9 it has kept a list of daily pages, but the list vanished at the end of every run. This week the log saves 3 days to a file, reads them back, and adds them up to 77. Then you learn to catch the errors a file can cause, starting with the most common one: the file is not there yet.

By the end of this chapter you will be able to:

  • write lines to a file with a with statement, mode "w", and an explicit newline;
  • predict what read(), readlines(), and a for line in f: loop hand back;
  • convert each line you read before you do arithmetic with it;
  • explain why the file is closed when the with block ends, even on an exception;
  • name a runtime error by its type from the last line of the traceback;
  • predict which block of a try and except runs, and which lines are skipped;
  • handle a missing file with the save-and-reload pattern, and explain why a bare except: hides real bugs.

Carry this line with you: a file holds text, not numbers; catch the type you expect.

Where we are

  • Already covered: Week 1 taught you to read an error from its last line. Week 2 gave you int() and str(), and the TypeError from "5" + 3. Week 3 gave you IndexError. Weeks 5 and 6 gave you accumulators and for loops. Week 9 gave you lists and append. Week 10 gave you dictionaries and KeyError. Week 11 gave you strip() and split().
  • This week: writing and reading files with a with statement, modes "w" and "r", what read(), readlines(), and a line loop hand back, the save-and-reload pattern, the error set by type, and try with except.
  • How they connect: every line you read from a file is a string, so Week 11's strip() and Week 2's int() are what turn it into a number. And every exception you catch this week is one you have already met by name.
  • Where we're going next: Week 13, on algorithms, takes the lists you can now save and load and asks how fast a program can search and sort them.

Three earlier ideas carry most of the weight. From Week 2, int("12") turns text into the number 12, and "5" + 3 raises TypeError. From Week 6, a for loop hands you one item per pass, and an accumulator starts at 0 before the loop. From Week 11, .strip() hands back a new string with the whitespace trimmed from both ends, and .split() cuts on whitespace. Spend extra time on Sections 3 and 6. The quiz leans on both, and so does every program that reads data from now on.

1. Write a file: give your program a memory

A paper notebook on your desk keeps what you wrote last night. Your program's variables are more like a whiteboard that someone wipes clean every time the program ends. A file is the notebook.

A file is a named store of text on the computer's disk that keeps its contents after a program stops running, so a later run can read back what an earlier run wrote.

To use a file, you open it. open() is the built-in function that takes a file's name and a mode and hands back a file object a program can read from or write to. A file object is the value open() hands back, which a program uses to write strings into a file or to read the file's text back out.

You almost always open a file inside a with statement, a statement written as with open(...) as f: that runs its indented block with the file under the name f and closes the file when the block ends, even when an exception is raised inside it.

Write mode is the mode "w" given to open(), which creates the file if it is not there and erases every line of an existing file of the same name before writing. Inside the block, write() is the file method that puts one string into a file opened for writing and adds nothing after it, not even a newline.

The newline character is the invisible character that ends one line of text and starts the next, typed in a Python string as a backslash followed by the letter n: "\n". A program writing lines to a file has to add it itself.

Worked example — save the reading log. This is the first half of the reading log's Week 12 stage. Predict what it prints.

daily = [12, 40, 25]
with open("reading_log.txt", "w") as f:
    for pages in daily:
        f.write(str(pages) + "\n")

Here is what happens, line by line.

  1. open("reading_log.txt", "w") creates a file named reading_log.txt in the folder where the program runs, and the with statement names it f.
  2. The loop runs 3 times. Each pass turns a number into text with str(), glues a newline onto the end with +, and writes that string.
  3. When the indented block ends, the file is closed.

The program prints nothing at all. Its work is on the disk: a file of 3 lines, 12, 40, and 25. You will read them back in Section 3.

Worked example — write mode starts over. An illustrative to-do file gets written twice. Predict the last line.

with open("tasks.txt", "w") as f:
    f.write("email\n")
    f.write("lunch\n")

with open("tasks.txt", "w") as f:
    f.write("gym\n")

with open("tasks.txt") as f:
    print(f.readlines())

Output

['gym\n']

The second open with "w" erased email and lunch before it wrote gym. The \n you see inside the quotes is how Python prints the newline at the end of the line; Section 2 explains it.

Misconception check. Students often think "w" adds new lines after the old ones, because "write" sounds like "write some more." That is tempting, because a notebook works that way. But mode "w" erases the file first, every time, so only gym survived. The cure: use "w" only when you mean "start this file over." Append mode is the mode "a", which adds new text after the lines a file already holds instead of erasing them; this course names it but does not teach it.

In practice (your tools). Open your free browser Python runner, paste the to-do program, and press Run. Then change the second "w" to "a", predict what prints, and run it again to see append mode keep all three tasks. The Python Tutorial's section 7.2, Reading and Writing Files, on docs.python.org, lists the modes.

Memory hook: "w" means start over.

2. Read a file: three ways to get the text back

A friend hands you a page of notes. You can take the whole page in one glance, tear it into a stack of strips with one line on each, or read it aloud one line at a time. Python gives you the same three choices.

Read mode is the mode "r", which opens an existing file for reading and is the mode Python uses when no mode is given. So open("fruit.txt") reads.

  • read() is the file method that hands back the whole contents of a file as one single string, newlines included.
  • readlines() is the file method that hands back a list of strings, one for each line of the file, with each string still ending in its newline.
  • A for line in f: loop walks the file one line per pass, and each line still ends in its newline.

Worked example — the fruit round trip. This is the pinned round-trip program. Predict all four lines.

fruits = ["apple", "banana", "cherry"]
with open("fruit.txt", "w") as f:
    for fruit in fruits:
        f.write(fruit + "\n")

with open("fruit.txt") as f:
    lines = f.readlines()
print(len(lines))
print(lines[0].strip())

with open("fruit.txt") as f:
    text = f.read()
print(type(text))
print(text.split())

Output

3
apple
<class 'str'>
['apple', 'banana', 'cherry']

Here is the reasoning.

  1. The first block writes 3 lines.
  2. readlines() hands back a list of 3 strings, so len(lines) is 3.
  3. lines[0] is 'apple\n'; .strip() trims the newline, so it prints apple.
  4. read() hands back the whole file as one string, and type(text) says so: &lt;class 'str'&gt;.
  5. .split() cuts that one string on whitespace, and a newline counts as whitespace, so it prints a list of the 3 words.

In words: readlines() gave you a list, and read() gave you one string.

Worked example — lines keep their newline. The reading log file from Section 1 holds 3 lines. Predict both programs.

daily = [12, 40, 25]
with open("reading_log.txt", "w") as f:
    for pages in daily:
        f.write(str(pages) + "\n")

with open("reading_log.txt") as f:
    lines = f.readlines()
print(lines)
print(len(lines))

Output

['12\n', '40\n', '25\n']
3
daily = [12, 40, 25]
with open("reading_log.txt", "w") as f:
    for pages in daily:
        f.write(str(pages) + "\n")

with open("reading_log.txt") as f:
    for line in f:
        print(len(line), len(line.strip()))

Output

3 2
3 2
3 2

Each line is two digits plus the newline, 2 + 1 = 3 characters. After .strip() the newline is gone, so 2 are left. The \n in the printed list is Python's way of showing that invisible character.

Misconception check. Students often think a line read from a file is the same as the line they see in a text editor, 12. That is tempting, because the newline is invisible in an editor. But the line Python hands you is '12\n', 3 characters long, and the extra character breaks comparisons such as line == "12". The cure: call .strip() on every line before you compare it or convert it.

In practice (your tools). In your browser runner, run the second program above, then change the last line to print(line == "12", line.strip() == "12") and predict both values before you run it. The Python Tutorial's section 7.2.1, Methods of File Objects, on docs.python.org, describes read() and line-by-line reading.

Memory hook: every line ends in a newline until you strip it.

3. Convert what you read: a file holds text, not numbers

A grocery receipt shows 12, 40, and 25 printed in ink. You can add them in your head, but the paper itself holds only marks. To a program, a file is that paper: every line is text, even when the text is made of digits.

Worked example — adding the raw lines. Predict what this prints.

daily = [12, 40, 25]
with open("reading_log.txt", "w") as f:
    for pages in daily:
        f.write(str(pages) + "\n")

total = 0
with open("reading_log.txt") as f:
    for line in f:
        total = total + line
print(total)

Output

TypeError

Nothing printed. On the first pass total is the number 0 and line is the string '12\n', and 0 + '12\n' asks Python to add a number to a string. That is the same TypeError that "5" + 3 raised in Week 2.

Worked example — the reading log's Week 12 stage. This is the pinned program. It writes the log and reads it back as numbers. Predict the output.

daily = [12, 40, 25]
with open("reading_log.txt", "w") as f:
    for pages in daily:
        f.write(str(pages) + "\n")

total = 0
with open("reading_log.txt") as f:
    for line in f:
        total = total + int(line.strip())
print(total)

Output

77

Here is the trace.

  1. Each line comes back as a string such as "12\n".
  2. strip() removes the newline, leaving "12".
  3. int() turns "12" into the number 12.
  4. The accumulator adds the 3 numbers: 12 + 40 + 25 = 77.

In words: the log saved 3 days and read back 77 pages, and the conversion is what made the arithmetic possible.

Worked example — the missing newline. This version forgets the "\n". Predict both lines.

daily = [12, 40, 25]
with open("reading_log.txt", "w") as f:
    for pages in daily:
        f.write(str(pages))

with open("reading_log.txt") as f:
    text = f.read()
print(text)
print(len(text.split()))

Output

124025
1

write() adds nothing after its string, so the three numbers ran together into one line, 124025, and split() found 1 piece instead of 3. No error appeared. The program ran and saved the wrong thing, so this is a logic error.

Here is the same pattern in a second setting, an illustrative step counter that saves 3 days.

steps = [4200, 6800, 5100]
with open("steps.txt", "w") as f:
    for count in steps:
        f.write(str(count) + "\n")

with open("steps.txt") as f:
    text = f.read()
print(text.split())
print(len(text.split()))

Output

['4200', '6800', '5100']
3

The quotes around each count in the printed list tell you they are strings. You would still need int() before adding them.

Misconception check. Students often think a file read gives numbers when the file holds digits. That is tempting, because the file looks like a column of numbers. But read(), readlines(), and a line loop always hand back strings. The cure: convert each line with int(line.strip()), or float(line.strip()) for decimals, before you do arithmetic.

In practice (your tools). Run the pinned reading-log program in your browser runner. Then add print(type(line)) inside the second loop, predict what prints 3 times, and run it to see &lt;class 'str'&gt; on every pass.

Memory hook: a file holds text, not numbers.

4. Let the with block close the file for you

A library book has a due date, and the library does not trust you to remember it; the system checks it back in for you. A with statement treats a file the same way: you never have to remember to close it.

An open file is a connection between your program and the disk. Closing it finishes the writing and lets other programs use the file. The with statement closes it when the block ends, on the last indented line or when an exception jumps out of the block.

Worked example — open inside, closed after. A file object has a closed attribute, True once the file has been closed. Predict both lines.

with open("notes.txt", "w") as f:
    f.write("hello\n")
    print(f.closed)
print(f.closed)

Output

False
True

Inside the block the file was open. One line after the block, it was closed, and nobody wrote a line of code to close it.

Worked example — closed even when something goes wrong. This program divides by 0 inside the block. Predict the output.

try:
    with open("notes.txt", "w") as f:
        f.write("hello\n")
        print(10 / 0)
except ZeroDivisionError:
    print("caught")
print(f.closed)

Output

caught
True

The division raised an exception in the middle of the block. Python closed the file on the way out, and then the except line you will meet in Section 6 caught the error. The last line confirms the file is closed.

Misconception check. Students often think they must close every file themselves with a separate line of code. That is tempting, because older examples online do it that way. But a with statement closes the file when the block ends, even on an exception, which a hand-written close line can miss. The cure: open every file with with open(...) as f: and let the block do the closing.

In practice (your tools). Run the first program in your browser runner. Then move print(f.closed) so it sits inside the block as the last indented line, predict what prints, and run it again.

Memory hook: the block opens it, and the block closes it.

5. Read a runtime error: name it by its type

A car's dashboard light does not tell you everything, but it tells you which system to check: oil, brakes, or fuel. The last line of a Python error does the same job.

An exception is the signal Python raises when something goes wrong while a program is running, which stops the program unless code is in place to catch that kind of problem. A traceback is the report Python prints when an exception stops a program; its last line names the exception type, and the text after the colon describes that particular case. An exception type is the name of the kind of problem an exception reports, such as ValueError or FileNotFoundError, which an except clause uses to decide whether to catch it.

You met a syntax error in Week 1: the parser refused the text and nothing ran. A runtime error is different. The program started, ran some lines, and then one line raised an exception. A logic error is different again: the program runs to the end and prints the wrong thing, as the missing newline did in Section 3.

Worked example — the error set. Each program below raises one exception. Read the type, never the message.

Seven pinned programs, each ending in one exception type, with any output printed before the error
Program What prints Exception type
pages = 0, print("before"), print(10 / pages) before ZeroDivisionError
daily = [12, 40, 25], print(daily[3]) nothing IndexError
log = {"atlas": 85}, print(log["comics"]) nothing KeyError
print("5" + 3) nothing TypeError
print(total), with no total assigned nothing NameError
print(int("3.5")) nothing ValueError
opening no_such_file.txt in an empty folder nothing FileNotFoundError

Three of these are new names this week.

  • ZeroDivisionError is the exception Python raises when a program divides a number by zero or takes a remainder by zero.
  • ValueError is the exception Python raises when a value has the right type but cannot be used, such as int() given the text 3.5 or the word forty-two.
  • FileNotFoundError is the exception Python raises when a program tries to open a file for reading and no file with that name exists in the folder.

Look at the first row again. The program printed before and then stopped, so the line after the division never ran. An exception stops the program at the line that raised it.

Here is the first row as a program, so you can see the output block and the type on its own line.

pages = 0
print("before")
print(10 / pages)
print("after")

Output

before
ZeroDivisionError

Misconception check. Students often think they need to understand the whole traceback, or the message after the colon, to fix an error. That is tempting, because the message is the longest part. But the type on the last line already tells you which kind of problem to look for, and the message wording can change from one Python version to the next. The cure: read the last line first, name the type, and then look at the line number above it.

In practice (your tools). In your browser runner, type each program from the table and run it. Before each run, write down the type you expect; after it, read only the start of the last line and compare. The Standard Library reference's Built-in Exceptions page on docs.python.org gives a one-line definition of each type.

Memory hook: read the last line; name the type.

6. Catch an error by type: which block runs

A delivery driver has a plan for one problem: "If nobody answers, leave the parcel with a neighbor." The plan does not cover a flat tire. A try statement is that kind of plan, written for one named problem.

A try statement is a statement made of a try block and one or more except blocks, which lets a program catch a named exception and keep running instead of stopping. The try block is the indented code under try: that Python runs first; if a line in it raises an exception, the rest of the try block is skipped. An except block is the indented code under an except line that runs only when the try block raises the exception type that line names, and is skipped otherwise.

Worked example — which block runs. This is the pinned program. Predict all three lines.

try:
    n = int("42")
    print("ok", n + 1)
except ValueError:
    print("not a number")

try:
    n = int("forty-two")
    print("ok", n + 1)
except ValueError:
    print("not a number")

try:
    with open("no_such_file.txt") as f:
        print(f.read())
except FileNotFoundError:
    print("no file yet")

Output

ok 43
not a number
no file yet

Here is the reasoning, one try statement at a time.

  1. int("42") works, so the try block runs to the end and prints ok 43, because 42 + 1 = 43. No exception, so the except block is skipped.
  2. int("forty-two") raises ValueError. The rest of the try block is skipped, and the except ValueError: block runs.
  3. Opening a file that does not exist raises FileNotFoundError, and the matching except block prints no file yet.

Worked example — the rest of the try is skipped. Predict all three lines.

try:
    print("before")
    print(10 / 0)
    print("after")
except ZeroDivisionError:
    print("cannot divide by zero")
print("still running")

Output

before
cannot divide by zero
still running

before printed. The division raised, so print("after") was skipped, the except block ran, and the program carried on past the try statement.

Worked example — the wrong type catches nothing. Predict what happens.

try:
    print(int("3.5"))
except ZeroDivisionError:
    print("caught it")

Output

ValueError

int("3.5") raised ValueError, and the only except block names ZeroDivisionError. The types do not match, so nothing catches the exception and the program stops.

Here is a try statement inside a loop, in an illustrative bike-share report where one dock reported "n/a".

docks = ["8", "n/a", "5"]
total = 0
for entry in docks:
    try:
        total = total + int(entry)
    except ValueError:
        print("skipped", entry)
print(total)

Output

skipped n/a
13

The bad entry was skipped, the loop went on, and the good entries added up: 8 + 5 = 13 bikes.

Misconception check. Students often think try catches everything that goes wrong inside it. That is tempting, because "try" sounds like "try anything." But an except block catches only the type it names, so except ZeroDivisionError: let the ValueError through. The cure: name the exact type you expect, the one you read on the last line of the traceback.

In practice (your tools). Paste the "rest of the try is skipped" program into Python Tutor at pythontutor.com and click Next one step at a time. Watch the arrow jump from the division straight to the except line, skipping print("after"). The Python Tutorial's section 8.3, Handling Exceptions, on docs.python.org, describes this order step by step.

Memory hook: catch the type you expect, and only that type.

7. Handle a missing file: the save-and-reload pattern

A new notebook has no notes in it yet. Nobody calls that an error; it is the first day. A program that loads saved data has the same first day, when the save file does not exist yet.

The save-and-reload pattern is the habit of writing a program's data to a file before it ends and reading that file back at the start of the next run, treating a missing file as a fresh start.

Worked example — the first run. In an empty folder, with no reading_log.txt yet, predict both lines.

loaded = []
try:
    with open("reading_log.txt") as f:
        for line in f:
            loaded.append(int(line.strip()))
except FileNotFoundError:
    print("no log yet, starting fresh")
print(loaded)

Output

no log yet, starting fresh
[]

The open raised FileNotFoundError, the except block printed the friendly line, and the program went on with an empty list.

Worked example — a later run. This time the log was saved first. Predict the output.

daily = [12, 40, 25]
with open("reading_log.txt", "w") as f:
    for pages in daily:
        f.write(str(pages) + "\n")

loaded = []
try:
    with open("reading_log.txt") as f:
        for line in f:
            loaded.append(int(line.strip()))
except FileNotFoundError:
    print("no log yet, starting fresh")
print(loaded)

Output

[12, 40, 25]

The file was there, so the try block ran to the end and the except block was skipped. Each line was stripped, converted, and appended, so the list came back as numbers.

Here is the pattern in a third setting, an illustrative password checker that loads its rule from a file when one exists and falls back to a default when it does not.

try:
    with open("password_rules.txt") as f:
        rules = f.read()
except FileNotFoundError:
    rules = "at least 8 characters"
print(rules)

Output

at least 8 characters

Misconception check. Students often think a missing file means the program is broken and should stop. That is tempting, because the traceback looks alarming. But on a program's first run the missing file is expected, and a crash would stop the user before they saved anything. The cure: wrap the loading code in try with except FileNotFoundError: and start from an empty value.

In practice (your tools). Run the first-run program in your browser runner and confirm it prints the fresh-start line. Then run the later-run program, and then the first-run program again: if your runner keeps files between runs, the second time it loads [12, 40, 25].

Memory hook: no file yet is a first day, not a crash.

8. Name the type: a bare except hides real bugs

A smoke alarm that someone silenced with tape never bothers anyone again, including on the night of a real fire. A bare except is that tape.

A bare except is an except line written with no exception type, which catches every exception, including the ones caused by typos and other real bugs, and so hides them.

Worked example — the hidden typo. This program adds up the reading log, but total is misspelled on the print line. Predict what prints.

daily = [12, 40, 25]
try:
    total = 0
    for pages in daily:
        total = total + pages
    print(totl)
except:
    print("could not add the log")

Output

could not add the log

The addition worked: total reached 77. Then print(totl) raised NameError, because totl was never assigned, and the bare except caught it and printed a message that blames the log. The real bug, a typo, stays hidden.

Worked example — let the real bug through. The same program names the type it expects.

daily = [12, 40, 25]
try:
    total = 0
    for pages in daily:
        total = total + pages
    print(totl)
except ValueError:
    print("could not add the log")

Output

NameError

Now the NameError is not caught, so the traceback appears, and its last line points straight at the typo. A loud bug is a bug you can fix.

Worked example — check a chatbot's claim. Suppose you ask a chatbot how to add a task to a saved list, and it answers: "Open the file with "w"; that adds your new line to the end." Run the program from Section 1 that tests exactly that claim. It printed ['gym\n']: the old tasks were erased, so the claim was wrong. The fix is append mode, "a", which this course only names, or reading the old lines first and writing them all back.

Misconception check. Students often think a bare except: is a safe default, because the program never crashes. That is tempting, because a crash feels like failure. But the crash was information, and the bare except threw it away and printed a misleading message instead. The cure: name the type you expect in every except line, and let every other exception stop the program loudly.

In practice (your tools). Ask your approved chatbot to write a program that reads numbers from a file and adds them up, "and make sure it never crashes." Check its code for a bare except:. If you find one, put a typo inside the try block, run it, and see whether the typo is hidden. The Python Tutorial's section 8.3 on docs.python.org shows except lines that name their types.

Honesty note: this chapter covers only the file and exception tools Week 12 needs. CSV and JSON files, the finally and else clauses of a try statement, and your own exception types belong to a later course. Python also has a raise statement that lets your own code signal an error; you will use it in a later course.

Caveat: the exact wording after the colon in a traceback can differ between Python versions, which is one more reason this course keys every error on its type alone.

Pause and choose one of these to think about before you read on:

  • (a) Think of an app that remembers something between uses, such as a game's high level, a notes app, or a step counter. What would it need to save, and what should it do on its very first run?
  • (b) Think of a time a device or website showed you a vague message like "something went wrong." Would a specific message, naming the kind of problem, have helped you, and how?

Memory hook: a loud bug is a bug you can fix.

Key terms

  • file — A named store of text on the computer's disk that keeps its contents after a program stops running, so a later run can read back what an earlier run wrote. (first used: 1. Write a file: give your program a memory)
  • open() — The built-in function that takes a file's name and a mode and hands back a file object a program can read from or write to. (first used: 1. Write a file: give your program a memory)
  • file object — The value open() hands back, which a program uses to write strings into a file or to read the file's text back out. (first used: 1. Write a file: give your program a memory)
  • with statement — A statement written as with open(...) as f: that runs its indented block with the file under the name f and closes the file when the block ends, even when an exception is raised inside it. (first used: 1. Write a file: give your program a memory)
  • write mode — The mode "w" given to open(), which creates the file if it is not there and erases every line of an existing file of the same name before writing. (first used: 1. Write a file: give your program a memory)
  • write() — The file method that puts one string into a file opened for writing and adds nothing after it, not even a newline. (first used: 1. Write a file: give your program a memory)
  • newline character — The invisible character that ends one line of text and starts the next, typed in a Python string as a backslash followed by the letter n; a program writing lines to a file has to add it itself. (first used: 1. Write a file: give your program a memory)
  • append mode — The mode "a", which adds new text after the lines a file already holds instead of erasing them. (first used: 1. Write a file: give your program a memory)
  • read mode — The mode "r", which opens an existing file for reading and is the mode Python uses when no mode is given. (first used: 2. Read a file: three ways to get the text back)
  • read() — The file method that hands back the whole contents of a file as one single string, newlines included. (first used: 2. Read a file: three ways to get the text back)
  • readlines() — The file method that hands back a list of strings, one for each line of the file, with each string still ending in its newline. (first used: 2. Read a file: three ways to get the text back)
  • exception — The signal Python raises when something goes wrong while a program is running, which stops the program unless code is in place to catch that kind of problem. (first used: 5. Read a runtime error: name it by its type)
  • traceback — The report Python prints when an exception stops a program; its last line names the exception type, and the text after the colon describes that particular case. (first used: 5. Read a runtime error: name it by its type)
  • exception type — The name of the kind of problem an exception reports, such as ValueError or FileNotFoundError, which an except clause uses to decide whether to catch it. (first used: 5. Read a runtime error: name it by its type)
  • ZeroDivisionError — The exception Python raises when a program divides a number by zero or takes a remainder by zero. (first used: 5. Read a runtime error: name it by its type)
  • ValueError — The exception Python raises when a value has the right type but cannot be used, such as int() given the text 3.5 or the word forty-two. (first used: 5. Read a runtime error: name it by its type)
  • FileNotFoundError — The exception Python raises when a program tries to open a file for reading and no file with that name exists in the folder. (first used: 5. Read a runtime error: name it by its type)
  • try statement — A statement made of a try block and one or more except blocks, which lets a program catch a named exception and keep running instead of stopping. (first used: 6. Catch an error by type: which block runs)
  • try block — The indented code under try: that Python runs first; if a line in it raises an exception, the rest of the try block is skipped. (first used: 6. Catch an error by type: which block runs)
  • except block — The indented code under an except line that runs only when the try block raises the exception type that line names, and is skipped otherwise. (first used: 6. Catch an error by type: which block runs)
  • save-and-reload pattern — The habit of writing a program's data to a file before it ends and reading that file back at the start of the next run, treating a missing file as a fresh start. (first used: 7. Handle a missing file: the save-and-reload pattern)
  • bare except — An except line written with no exception type, which catches every exception, including the ones caused by typos and other real bugs, and so hides them. (first used: 8. Name the type: a bare except hides real bugs)

Summary

  • A file keeps text on the disk after the program ends.
  • Open every file with a with statement; the block closes it, even on an exception.
  • Mode "w" creates a file or erases it first; mode "r" reads and is the default.
  • write() adds nothing, so write the "\n" yourself.
  • read() hands back one string; readlines() hands back a list of lines.
  • Every line you read is a string ending in a newline: strip it, then convert it.
  • Read a runtime error from the last line and name it by its type.
  • An except block runs only for the type it names; the rest of the try block is skipped.
  • Catch FileNotFoundError to treat a missing save file as a fresh start.
  • Never write a bare except:; it hides real bugs.

Check your understanding

Work these before looking at the answers — they are ungraded, and the answers (with reasoning) are at the bottom of the page.

  1. A dice game saves its rolls (an illustrative example). It opens rolls.txt with "w" and writes "3\n" and "5\n". Then it opens rolls.txt with "w" again and writes "6\n". Finally it reads the file with readlines() and prints the list and its length. Predict both lines.
  2. A tip jar program writes the lines "7\n" and "12\n" to tips.txt, then reads the file with for line in f: and total = total + line, starting from total = 0. Predict what happens, and fix the loop so it prints the total of the tips.
  3. A running coach's app has a try block of three lines, print("start"), then laps = int("ten"), then print("done"), followed by except ValueError: with print("bad number") in its block. Predict every printed line.
  4. A bike-share app runs docks = {"north": 6} and then a try block that prints docks["south"], with except IndexError: printing no such dock. Predict what happens, and name the one change that makes it print no such dock.

Answers (worked reasoning — read after attempting)

  1. It prints ['6\n'] and then 1. The second open with "w" erased the 3 and the 5 before it wrote the 6, so the file holds one line, still ending in its newline. If you predicted 3 lines, you met the ""w" appends" trap; write mode always starts over.
  2. It prints nothing and raises TypeError, because on the first pass 0 + '7\n' adds a number to a string. Fix the loop body to total = total + int(line.strip()): the strip removes the newline, int() makes a number, and the program prints 19, since 7 + 12 = 19.
  3. It prints start and then bad number. int("ten") raises ValueError, so the rest of the try block, print("done"), is skipped, and the matching except block runs.
  4. It prints nothing it meant to, and the program stops with KeyError. A missing dictionary key raises KeyError, not IndexError, so the except block's type does not match and catches nothing. Change except IndexError: to except KeyError:, and the program prints no such dock.

Next up in this module: the Readings & Resources page, the lecture tutorial, the practice set, and the quiz — and next week, the lists you can now save and reload meet a new method of measuring work: counting the comparisons a search makes.

Built with The Course Maker · samples.thecoursemaker.com