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

Lecture: File Input/Output & Exceptions

Introduction to Computer Science Free sample edition

Lecture script · about 15–20 minutes spoken · Week 12

Opening

Picture a field-biology student counting plants along a trail every morning. Each run of their program prints the count, and then the count is gone, because a program forgets everything when it stops. Or picture a lab assistant whose program meets one typo in a data sheet and stops dead, halfway through the work. This week fixes both problems. A program learns to remember between runs, and to keep going when one line of input is wrong.

You've built the pieces already. Week 1 taught you to read an error from its last line. Week 2 gave you int and str. Week 9 put the reading log's pages in a list, and Week 11 gave you strip and split. Next week, in the module on algorithms, you'll search and sort lists like the ones you can now save and load.

Here's the plan. We'll write a file, read it back, and convert what we read. Then we'll name runtime errors by type, catch them, handle a missing file, and see why a bare except hides bugs.

1. Write a file

Think of a whiteboard and a notebook. Whatever you write on the whiteboard gets wiped when the room is cleaned. Whatever you write in the notebook is still there next week. Your program's variables are the whiteboard. 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. You open one with the built-in function open, almost always inside a with statement. A with statement is a statement written as with open, the file's name, as f, and a colon. It 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.

Opening a file takes a mode. 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.

Here's the first half of the reading log's Week 12 stage. A list called daily holds three days of pages: 12, 40, and 25. The program opens a file called reading log dot txt in write mode. Then a loop writes each day: it turns the number into text with str, adds a newline on the end, and calls write. The newline character is the invisible character that ends one line of text and starts the next. You type it in a Python string as a backslash followed by the letter n, and you add it yourself, because write adds nothing after its string.

The program displays nothing. Its work is sitting on the disk: a file of three lines, 12, 40, and 25.

Now a warning about write mode. Picture a little to-do program. It writes email and lunch to a file called tasks dot txt. Then it opens the same file with w again and writes gym. Then it reads the file back.

Pause and try this. After the second open in write mode and the line gym, what list of lines comes back from the file?

Remember what w does before it writes anything.

Here's the answer. Only one line comes back: gym, with its newline. Write mode erased email and lunch before it wrote gym, because w always starts the file over.

There's a mode that adds to the end instead, called append mode, and this course only names it.

2. Read a file three ways

Imagine a page of notes. You can take it in whole, cut it into strips, or read it aloud line by line. Python gives you those three choices.

First, read mode is the mode r, which opens an existing file for reading and is the mode Python uses when no mode is given. Then you choose how to read. 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. And a for loop over the file walks it one line per pass, each line still ending in its newline.

Here's the pinned round trip. It writes apple, banana, and cherry to a file called fruit dot txt. Readlines gives a list of length 3, and its first line, stripped, is apple. Read gives class str, a single string, and splitting it gives the three fruit names.

Now try it on the reading log. Readlines gives a list of three strings, and each one ends in a backslash n. That's 12 then the newline, 40 then the newline, 25 then the newline. And a loop that displays the length of each line, and then the length after strip, displays 3 and 2, on every pass. Each line is two digits plus the newline, and 2 plus 1 is 3. Strip takes the newline off and leaves 2.

Pause and try this. A line read from the reading log looks like 12 in a text editor. Why does its length come out as 3?

Count every character, including the one you can't see.

Here's the answer. The line is 12 followed by the newline character, and that's 3 characters. Strip removes the newline, which leaves the 2 you expected.

Every line ends in a newline until you strip it.

3. Convert what you read

Picture a printed receipt with the numbers 12, 40, and 25 on it. You can add them in your head, but the paper only holds ink. To a program, a file is that paper. Every line is text, even when the text is made of digits.

So watch what happens if you forget. A loop adds each raw line to a total that starts at 0. On the first pass, Python is asked to add 0 to the string 12 with its newline, and the run stops with a TypeError, the same type you met in Week 2.

Here's the pinned Week 12 stage, done right. For each line, the program calls strip to take off the newline, then int to turn the text into a number, and only then adds it to the total. It displays 77, because 12 plus 40 plus 25 is 77.

One more trap lives on the writing side. Leave out the backslash n, and the three counts run together: the file holds one line, 124025, and split finds 1 piece instead of 3. No error appears, so it's a logic error.

Pause and try this. The reading log program adds int of each stripped line and displays 77. Which two steps turn a line like 12 with its newline into a number you can add?

Think about what each of the two calls removes or changes.

Here's the answer. Strip removes the newline, and int turns the text 12 into the number 12. Only after both can the line be added to the total.

A file holds text, not numbers.

4. Let the with block close the file

Think of a library that checks your books back in the moment you walk through the door. A with statement treats a file the same way.

An open file is a connection between your program and the disk, and closing it finishes the job. The with statement closes the file when its block ends, whether the block ran to its last line or an exception jumped out of it.

Here's a small program that proves it. It opens a file called notes dot txt in write mode, writes hello, and inside the block displays f dot closed. That displays False. Then, one line after the block, it displays f dot closed again, and that displays True. Nobody wrote a line of code to close the file.

Now make something go wrong. Inside the block, the program writes hello and divides 10 by 0, and an except for ZeroDivisionError outside displays caught. The run displays caught, and then f dot closed displays True. The file was closed on the way out.

Pause and try this. In the second program, the division by 0 stops the block halfway through. Why is f dot closed still True at the end?

Ask who is responsible for closing the file.

Here's the answer. The with statement closes the file whenever its block ends, even on an exception. So the file was closed before the except line ever ran.

The block opens it, and the block closes it.

5. Read a runtime error by its type

Think of a car's dashboard light. It doesn't explain the whole problem, but it tells you which system to check: oil, brakes, or fuel. The last line of a Python error does that 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. So you read it from the bottom, and you name the type. You never need the wording after the colon.

Here are the seven types this week, from the pinned error set. Dividing by a pages variable that holds 0 displays before and then stops with ZeroDivisionError. Asking for index 3 of a list of three items stops with IndexError. Looking up comics in a dictionary whose only key is atlas stops with KeyError. Adding the string 5 to the number 3 stops with TypeError. Displaying a name called total that was never assigned stops with NameError. Calling int on the text 3.5 stops with ValueError. And opening a file called no such file dot txt, in an empty folder, stops with FileNotFoundError.

That's the difference from Week 1's syntax error, where the parser refused the text and nothing ran at all. A runtime error happens while the program is running.

Pause and try this. The pinned ZeroDivisionError program displays before and then stops. Does the line after the division ever run?

Think about where the exception stops the program.

Here's the answer. No. An exception stops the program at the line that raised it, so the line after the division never runs.

Read the last line, and name the type.

6. Catch an error by type

A delivery driver has a plan for one problem: if nobody answers, leave the parcel with a neighbor. That plan says nothing about a flat tire. A try statement is a plan like that, 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.

Here's the pinned program, three try statements in a row. The first calls int on the text 42, which works, so it displays ok 43, because 42 plus 1 is 43. The second calls int on 42 spelled out in letters, which raises ValueError, so the except block displays not a number. The third opens a file that doesn't exist, which raises FileNotFoundError, and its except block displays no file yet.

Now a program where the try block displays before, then divides 10 by 0, then would display after. Its except names ZeroDivisionError and displays cannot divide by zero, and one more line after the whole try displays still running.

Pause and try this. In that program, which three lines appear, and which line is skipped?

Follow the try block line by line until something goes wrong.

Here's the answer. It displays before, then cannot divide by zero, then still running. The line that would display after is skipped, because the division raised and the rest of the try block never ran.

And notice what a try does not do. If the except names ZeroDivisionError but the try block calls int on 3.5, the ValueError isn't caught at all, and the run stops. An except catches only the type it names.

7. Handle a missing file

Think about a brand-new notebook. It has no notes in it yet, and nobody calls that an error. It's the first day. A program that loads saved data has a first day too, when the save file doesn't exist yet.

That's the 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.

Here's the reading log's version. A list called loaded starts empty. Inside a try, the program opens the reading log and, for each line, strips it, converts it with int, and appends it to loaded. The except names FileNotFoundError and displays no log yet, starting fresh. Then the program displays loaded.

On the very first run, in an empty folder, there's no file. The open raises FileNotFoundError, so the run displays no log yet, starting fresh, and then an empty list. On a later run, after the log was saved, the try block runs to the end and the run displays the list 12, 40, 25, as numbers.

Pause and try this. On the later run, the file is there. Does the except block run at all?

Think about when an except block runs.

Here's the answer. No. The try block raised nothing, so the except block was skipped, and the list came back as 12, 40, and 25.

No file yet is a first day, not a crash.

8. Name the type: a bare except hides bugs

Picture a smoke alarm that someone silenced with tape. It never bothers anyone again, and that includes the night of a real fire.

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.

Here's how it bites. Inside a try, a program adds up the reading log's three days, so the total reaches 77. Then it displays a name spelled t o t l, a typo for total. The bare except displays could not add the log. The real problem was a NameError, and the bare except swallowed it and blamed the log.

Change the bare except to except ValueError, and run it again. Now nothing catches the NameError, the traceback appears, and its last line points straight at the typo.

This is also how you check a chatbot. Suppose one tells you that write mode adds your new line to the end. Run the to-do program from the first section. It returns only gym, so the claim was wrong. The Python Tutorial's sections 7.2 and 8.3, on docs.python.org, are where files and try are written down.

Pause and try this. The bare except program displays could not add the log. What was the real problem, and why didn't you see it?

Think about what a bare except catches.

Here's the answer. The real problem was a NameError from the typo t o t l. The bare except catches every exception, so it hid the NameError behind a message about the log.

A loud bug is a bug you can fix.

Closing

Let's pull it together. A file keeps text after the program ends, and write mode starts it over. Read gives one string, readlines gives a list, and every line ends in a newline until you strip it. A file holds text, not numbers, so the reading log strips and converts each line to reach 77. The with block closes the file, even on an exception. The last line of a traceback names the exception type. An except block runs only for the type it names, and the rest of the try block is skipped. The save-and-reload pattern treats a missing file as a fresh start. And a bare except hides real bugs, so name the type.

Next in this module come the slide deck, the Readings and Resources page, the lecture tutorial, the practice set, the quiz, and the Coding Lab. Then, in Week 13, Algorithms: Searching, Sorting & Growth, you'll count how much work a search does on the lists you can now save and load.


Built with The Course Maker · samples.thecoursemaker.com