Week 8: More Top down design

Class Recordings

To access recordings, sign in with your @swarthmore.edu account.

Monday

Section 1 (Joshua)

Section 2 (Kevin)

Wednesday

Section 1 (Joshua)

Section 2 (Kevin)

Friday

Section 2 (Kevin)

Announcements

  • Lab 7 available now, design due Saturday night

  • Quiz 3 this Friday, 10/29

Week 8 Topics

  • incremental testing and development

  • prototyping functions

Monday

File Input/Output

A file is a sequence of data that is stored on your computer. For many tasks, especially tasks that use large amounts of data, input data will come from one or more files, and you will write output to a file instead of to the screen.

A file is typically made of many lines. There is a special newline character that is stored at the end of each line in a file: "\n". However, it is not visible when you look at the file.

Today, we’ll use a running example using a file named bestInShow.txt. We’ll also look at an example file, colors.txt that has a list of color names.

First, let’s look at these file in atom:

  • colors.txt:

    Almond
    Antique Brass
    Apricot
    Aquamarine
    Asparagus
    Atomic Tangerine
    Banana Mania
    Beaver
    Bittersweet
    Black
    ...
  • bestInShow.txt:

    2018,Whippet,Whiskey
    2017,Brussels Griffon,Newton
    2016,Greyhound,Gia
    2015,Skye Terrier,Charlie
    2014,Bloodhound,Nathan
    2013,American Foxhound,Jewel
    ...

In this file, data about each winner is stored on a separate line. Each line has the same format:

Year,Breed,Name

To open a file, the syntax is: <filevar> = open(<filename>, <mode>)

  • <filevar> is what your program will call the file.

  • <filename> is the name of the file, in this case colors.txt or bestInShow.txt.

  • <mode> is how you plan to use the file. "r" is for reading, "w" is for writing.

To close a file, execute: <filevar>.close()

There are a couple of ways that you can read data from a file. Here is perhaps the simplest:

infile = open("myfile", "r")
for line in infile:
    # process one line of the file
infile.close()

You can also read all the lines in at once (be careful using this with large files!):

infile = open("myfile", "r")
# lines is now a list of strings, one for each line of the file
lines = infile.readlines()
for line in lines:
    # process one line at a time
infile.close()

Let’s start by just trying to see the contents of the file:

infile = open("colors.txt", "r")
for line in infile:
    print(line)
infile.close()

Is the output of this code snippet what you expected? How is it different than the input file?

The first thing you’ll probably want to do with a file is remove the newline character from the end of the line. You can do this with the strip() method.

For files with multiple pieces of data per line, you’ll want to break the line up into those individual pieces. Do this with the split() method. This will take a single string and return a list of "words" — it treats spaces like dividers for different pieces of data.

Common String methods for file I/O

  • line.strip() — remove trailing whitespace (e.g., spaces, tabs "\t", newlines "\n")

  • line.split() — treat line as a list of strings separated by whitespace. return that list

  • line.split(<pattern>) — like line.split(), but treat as list of strings separated by <pattern>

List of lists

We’ve talked over the semester how a lists can contain any type of data. Lists can even contain other lists. Lists of lists are common with when doing file I/O. If each line is a list of data, then its common to store load the entire contents of the file in to a big list, where each element is itself a list representing data from one line of the file.

Let’s modify our winners.py program to store our information in a list of lists called winners:

Each winner is a list containing year, breed, and name.

winners = [ ['2018', 'Whippet', 'Whiskey'], ['2017', 'Brussels Griffon', 'Newton'], ['2016', 'Greyhound', 'Gia'], …​ ]

What would winners[0] evaluate to? What about winners[1]?

You can use double indexing to get at the data inside the winners list.

  • winners[0][0] yields 2018

  • winners[0][1] yields Whippet

  • winners[1][1] yields Brussels Griffon

Let’s go back to our program and modify it to store the winners information in a list of lists:

infile = open("bestInShow.txt", "r")
winners = []
for line in infile:
    winner = line.strip().split(",")
    winners.append(winner)
infile.close()
print(winners)
print("There are %d winners in the list." % (len(winners)))

Wednesday

Working with lists of lists

Last class we saw how to read and parse a text file into a list of lists. With the data in a more python friendly format, we can use the list of lists to explore the data.

Let’s start by writing a function get_winners(winners, breed) that prints all the winners that match a specified breed. Work with a partner to design, implement and test your function. One thing you will need to think about is how to get access to the breed of each winner in the list of lists, preferably in a loop. If there are no winners of a particular breed, you should print a helpful message instead of printing nothing.

Adding winners

Since lists are mutable, we can update our list of lists structure inside python. Let’s write an add_winner(winners, year, breed, name) function that adds a new winner to our winners list. Work with a partner to answer the questions below before writing your solution.

  1. Does add_winner need to return anything?

  2. What are the types of the parameters for the add_winner function?

  3. How is each winner stored in the winners list?

  4. How will you use the input parameters provided to perform the task of adding a new winner?

  5. How can you test your function after writing it?

Implement and test your function.

More robust error handling with try/except

Our solution so far to this program started with the load_winners("bestInShow.txt") function call and assumed that the file bestInShow.txt existed in the current directory. But what would happen if this were not the case? Try changing the filename in your program to missing.txt and run the program. What happens?

One possible solution to this problem is to check if a filename exists before attempting to open it. While this is possible in python3, it requires importing some extra libraries. Not a big deal, but it’s just more specific library details to learn. Another option is to use python’s built-in try/except mechanism to detect the error and handle it a bit more gracefully than we do now.

The general format for try/except is

try:
   #code that may generate an exception goes here
except <ErrorNameType> as <VAR>:
   #exception handling code goes here

an example might be

try:
   myfile=open(fname, 'r')
except FileNotFoundError as e:
   print(e)  # report error, but do not exit
   return [] # return an empty list

When python encounters a try/except block, it tries to executes the code in the try block. If nothing goes wrong, the code continues to run as normal. If an exception happens inside the try block, python will check if the the exception type matches the ErrorNameType and if it does, it will run the body of the except block.

Friday

Quiz 3

This Friday, 10/29

Lab 7

Walk through the details of this Top-Down Design lab

In class exercises

Recap the solutions, Functions, Graphics, Object-Oriented Programming and Top-Down Design Observation and feedback from recent labs and quizzes.

Writing Files

Time permitting.

In addition to reading from files, you can also write files with python. We need to be a little careful here, because python can potentially overwrite important data. Opening a file for writing is similar to opening for reading.

output = open("savedWinners.txt", 'w')

We simply change the second parameter from r to w.

To write to a file, use the write() method to write a string to the file. Python does not automatically add a newline, so you usually need to add this manually.

Remember to close the file at the end of writing with the close() method.

In addition to reading from files, you can also write files with python. We need to be a little careful here, because python can potentially overwrite important data — make sure to double-check the filename before writing! To write a file, you’ll need to pass in a different argument to the open function’s mode parameter.

mode Meaning to Python

r

Open file for reading only, starting at the beginning of the file.

w

Open file for writing only, starting at the beginning of the file. If the file isn’t empty, this will delete the contents — it "truncates" the file!

a

Open file for writing only, starting at the end of the file. This mode does not delete the contents, it’s meant for appending to the end of a file.

r+

Open file for both reading and writing, starting at the beginning of the file. While this may seem like the best of both worlds, it’s relatively rare for a program to read and write the same file at once.

After opening a file for writing, you can write to it with the file’s write() method. Note that Python does not automatically add a newline (\n) after a call to write() like it does for print(). You can add them to the file by including \n in the string you tell python to write. For example, to write a series of integers to a file:

# Open file for writing.
f = open("output.txt", "w")

# Write the numbers 0-9 to the file, each on a separate line (separated by a newline character \n).
for i in range(10):
    f.write("%d\n" % (i))

# Close the file when done.
f.close()

Saving Winners to a File

Let’s try writing the dog show winners, including any that you’ve added with add_winner(), to a file. Add a save_winners() function to your program. In it, you should:

  1. Open the file:

    output = open("savedWinners.txt", "w")
  2. Write each winner in the same format as the original bestInShow.txt file:

    year,breed,name
    year,breed,name
    ...
  3. Close the file:

    output.close()