Lab 8: Practice with Modules and Files
Goals
After the lab, you should be proficient at
- reading and processing data from files
- writing data to files
- creating our own modules
- handling exceptions
- reading numeric data from files
- solving problems with lists
Objective: Review
Review the slides for today's lab.
Objective: Set Up
- Set up the help client:
run runHelpClient &
- Copy
/csdept/courses/cs111/handouts/lab8
and all of its contents, recursively, into yourcs111
directory. This way, you don't have to create thelab8
directory first. Otherwise, you could first create thelab8
directory and then copy all of the contents of the/csdept/courses/cs111/handouts/lab8
directory (i.e., add a * to thecp
command) into yourlab8
directory.
Objective: Programming in Python
We'll practice writing several Python programs, each in their own text file. Name the files, as usual.
Your programs will be graded on correctness, style, efficiency, and how well you tested them. Make sure you adhere to the good development and testing practices we discussed in class. Your code should be readable and your output should be useful and well-formatted.
After you've developed a correct solution to each program, restart IDLE or close and reopen the IDLE "shell" by running the program again (using F5), demonstrate that the program works using several good test cases, and save the output to a file named lab8.x.out, where x is the problem number.
- (15) Creating a module. Modules are a way that
we can make our code easier to reuse and share. We've used modules
but haven't made our own modules explicitly. That changes now.
Copy (one of your)
lab7.8.py
and name itcaesarcipher.py
. Create a new file calledlab8.1.py
. Move themain
function and calling the main function fromcaesarcipher.py
intolab8.1.py
.Confirm:
caesarcipher.py
should contain only the definitions of the encoding functions and the test functions, comments at the top that describe the module, and maybe constants.Near the top of
lab8.1.py
, import your module by adding an import statement:from caesarcipher import *
Run
lab8.1.py
to confirm that it still works as expected.Next, modify
caesarcipher.py
to call your test functions at the bottom of the file. Runlab8.1.py
. What happened?To handle that issue, we need to add some code into
caesarcipher.py
: put the calls to the test functions into the body of anif
statement, specifically:if __name__ == "__main__":
Run
caesarcipher.py
. What happens?Run
lab8.1.py
. What happened?Reflection: Explain in comments in
caesarcipher.py
what the effect of adding thatif
statement was, on both caesarcipher.py and lab8.1.py.For your .out file, demonstrate that
lab8.1.py
works as expected. - (20) Modify
caesarcipher.py
such that it encodes many phrases using the Caesar Cipher program. Specifically, you will add a function calledencodeFile
that takes as parameters a filename (as astr
) and a key and returns the whole file encoded, as a string, preserving new line characters.Write a function to test this function. For example, process the
data/phrases.txt
file that you copied from thehandouts
directory. Better than starting withdata/phrases.txt
, you should create your own (simpler) files to test the encoding. What would be good, smaller files that would help show that your code works?Note: We're keeping the data files in a separate directory from the Python programs, which is good practice.
Copy
lab8.1.py
intolab8.2.py
. Then, modify itsmain
function such that it prompts the user for (1) the name of a file that contains phrases that need to be encoded and (2) a key, reads the file of phrases to be encoded, and outputs the encoded phrase.Example final output:
This program will encode a whole file using Caesar ciphers. Enter the name of a file to encode: data/song.txt Enter an encoder key (an integer between -25 and 25): 1 The encoded file is uijt pof hpft pvu up uif pof j mpwf uijt pof hpft pvu up uif pof j mfgu cfijoe
Doesn't that make testing the encodings a little easier, since you don't need to type out the whole phrase every time you test?
- (15) Update
caesarcipher.py
so that it has a function calledwriteEncodedFile
that takes as parameters the encoded message and the name of the file to write to, both as strings. Note that we can't write use test.testEqual to test the writing of a file. How can you test that your program works?Copy
lab8.2.py
aslab8.3.py
and modify themain
function such that it also takes as input the encoded message output file's name. You may want to assume that the output files always get written to thedata
directory so that you don't clutter yourlab8
directory with files.The idea is that now you can encode files that you can give to others to decode (and vice versa).
Example output:
What is the name of your file to encode? phrases.txt What is the name of the file to output the encoded file to? encoded.txt What is the key to use to encode? 12 Your message has been successfully written to data/encoded.txt
Note: I broke up the large problem of encoding files using a Caesar cipher and writing the result into another file into multiple, smaller problems, each of which is easier to tackle than tackling the whole problem all at once. This is an important problem-solving skill to develop. You may feel like breaking the problem into smaller problems slows you down, but it usually doesn't because you spend less time debugging the smaller pieces than if you had tackled it all at once. You'll get lots of practice solving problems in this class--including on the next problems!
- (15) Modify
caesarcipher.py
to do exception handling when reading the file and when writing to the file. When a problem with reading or writing a file occurs, display a descriptive error message and then exit the program. To exit the program, you'll need toimport sys
at the top of the program and then callsys.exit()
. Update the doc strings for the functions accordingly.Demonstrate that the program works as expected on files that exist and displays an error message on files that don't. For writing files, try writing to a location that you don't have permission to write to, e.g.,
/etc/myfile.txt
Note that we can't set up our test functions to be able to check that the exception behavior works because of how we have our functions set up.Save this output in
lab8.4.out
. - (35) The system of scoring an Olympic gymnast is based on two separate
panels of scores. The A panel judges the requirements, difficulty,
and connections of a routine. The scoring starts at zero and then
adds points accordingly. The B panel judges the execution of a
routine, and the scoring starts at 10 with points deducted
accordingly for execution and for any applicable violations such as
stepping out of bounds or being over the time limit.
For each panel of judges, the lowest and highest scores are dropped (to prevent judges from biasing the results) and then averaged. The two panels are then added together for the final score. A very good score will range in the 15s and 16s.
Your task:
- Read in a file containing the gymnastics scores. (The file
name can be a constant in your program.) The first line of the file
is the already-averaged difficulty score. The remaining six lines are the
judges' execution scores. (You cannot assume that the execution
scores are sorted.)
Example input file:
5.7 8.3 9.1 8.0 8.9 8.8 8.5
- Calculate the average score for the execution scores, as described above.
- Display the judges' scores and the final score in the format
shown below.
Example output:
Gymnastics Scores for data/scores.dat -------------------------------------------------------- Judges Execution Scores: 8.0 8.3 8.5 8.8 8.9 9.1 Average Execution Score: 8.625 Average Difficulty Score: 5.7 The Final Score: 14.325
Your output does not need to display the scores in sorted order. However, the output should be formatted as above.
Example files are
data/nastia.dat
anddata/shawn.dat
Breaking Down the Problem: Your final program should have at least 3 functions:
- A function that takes as a parameter the name of the file and returns a list of the scores (as floats) that are in the file.
- A function that takes as a parameter the list of scores (as floats) and returns the "unbiased" average.
- A
main
function
- Read in a file containing the gymnastics scores. (The file
name can be a constant in your program.) The first line of the file
is the already-averaged difficulty score. The remaining six lines are the
judges' execution scores. (You cannot assume that the execution
scores are sorted.)
Finishing up: What to turn in for this lab
- When you, as a pair, are ready to submit OR if you are at the
end of the lab period, run
pairturnin.sh labx partnerusername
wherelabx
is the name of the lab you are submitting andpartnerusername
is your partner's username on the lab machines (the person whose account you are not using to write the code). For more information about the command, see the wiki.If you want to copy your pairs' work into your
cs111
directory--either just to have it or to work on your code on your own--use the scriptstartup.sh
. Run this command from the account that you want For example, run startup.sh labx partnerusername
wherelabx
is the name of the lab you're working on andpartnerusername
is your partner's username on the lab machines.For more info, see the wiki.
- If you complete the lab on your own after the lab
period, submit
your lab into your
turnin
directory. - Create the printable lab assignment, using the
createPrintableLab
command:
createPrintableLab <labdirname> - View your file using the
evince
command. - Print the file using
the
lpr
command. - Log out of your machine when you are done.
Perform the following steps from
your cs111
directory.
Note that each command
below links to a page with more information about using the
command.
Labs are due at the beginning of Friday's class. You should
hand in the printed copy at the beginning of class, and the
electronic version should be in the turnin
directory before Friday.
Ask well before the deadline if you need help turning in your assignment!
Grading (100 pts)
- Python programs: 100 pts; see above for breakdown