The starter
What was needed for the Python prep assignment?
A lot
- Processing command line arguments
- Creating appropriate file names
- Opening files with error handling
- Creating list or dictionary for letter counts
- Reading the input file
- Incrementing the appropriate letter counts
- Displaying the letter counts
And maybe even more
- Adding the appropriate hash-bang line
- Satisfying pylint
- Adding some comments
References for the harder stuff
- Python Data Structures — lists, sets, dictionaries
- Python Errors and Exceptions
One solution
View here or download with a click.
This one has a lot of checking for I/O errors and has even passed through pylint.#!/usr/bin/env python """Script to count the number of times each letter appears in a file""" import sys import string def main(file_name): """Counts the number of time each letter appears in a file""" in_file_name = file_name + '.txt' out_file_name = file_name + '.count' try: in_file_hand = open(in_file_name, 'r') except IOError as read_open_io_error: print 'Failed to open {0} for reading: {1}'.format( in_file_name, read_open_io_error.strerror) return 1 try: out_file_hand = open(out_file_name, 'w') except IOError as write_open_io_error: print 'Failed to open {0} for writing: {1}'.format( in_file_name, write_open_io_error.strerror) in_file_hand.close() return 1 letter_count = {} for upper_char in string.ascii_uppercase: letter_count[upper_char] = 0 for line in in_file_hand: for any_char in line: if any_char.isalpha(): upper_char = any_char.upper() letter_count[upper_char] = letter_count[upper_char] + 1 in_file_hand.close() for upper_char in string.ascii_uppercase: out_file_hand.write("{0}: {1:4d}\n".format( upper_char, letter_count[upper_char])) out_file_hand.close() return 0 if __name__ == "__main__": if len(sys.argv) < 2: print 'usage: {0} filename'.format(sys.argv[0]) sys.exit(1) else: sys.exit(main(sys.argv[1]))
How about another one?
Regular expressions
Start with a serious study of the
re
module.
The group
method
re
module, inspired by
Perl’s
regular expression
and similar to JavaScript’s RegExp
,
is very useful at extracting the interesting parts of a string.
Suppose you wanted of tester for the regular expression questions on the first exam. You can do that with a Python program. Remember: most of the code is for the testing.
Processes and subprocesses
Consider the task of finding disk hogs. We want a command that we can search
a user’s home directory looking for the largest file that is
owned by the user and isn’t a compressed archive file.
Compressed archive files are those whose names end in
.zip and
.tar.bz2 and
files less than 100 Mbtyes in size aren’t even worthy of consideration.
We want to be able to run this program as
sooie username
Using find
Start by creating a single-line command that uses find to generate a list of candidate files, that is, those that satisfy the following criteria:
- located in the user’s home directory
- greater than 100 Mbytes
- with names that don’t end with .zip or .tar.bz2
Test out your find, but use
the full path name for find.
(Use the which
command to determine the full path name.)
Using Python’s shlex
Open up the Python
documentation for subprocess
and
make your way down to the use of
shlex.split
in section 17.1.1.2 .
Start up Python and
apply shlex.split
to your
find command. (Remember to use
the full path for find.)
This is very close to the format used by the Linux
execve
system call.
Take note of where the user’s name is used in the list returned
by shlex.split
.
Using Python’s subprocess
This time stat up Python and type the following commands.
import shlex, subprocess args = shlex.split('ls -l /etc') p = subprocess.Popen(args) p.wait() exit()
You have run ls from Python!
Let’s try again, but this time we’ll route the output of ls into a pipe that can be read as a file by Python.
import shlex, subprocess args = shlex.split('ls -l /etc') p = subprocess.Popen(args,stdout=subprocess.PIPE) p.stdout.readline() p.stdout.readline() p.stdout.readline()[:-1] p.stdout.close() p.wait() exit()
Writing the program
We’re going to do this through a serious of steps. If you are having trouble with a step (which I am certain will happen), you can press the link to download the hint.
Actually, start by saving this to the file sooie. Be sure to make sooie executable.
#!/usr/bin/env python """Looking for disk hogs""" import sys import os def main(username): """Python function to find large files""" return 0 if __name__ == "__main__": if len(sys.argv) < 2: print 'usage: {0} username'.format(sys.argv[0]) sys.exit(1) else: sys.exit(main(sys.argv[1]))
Finding home
Extend your Python program so that it can be run with the following command
sooie username
and does nothing more than check if there really is a directory called /home/username. Be like the pros, and Google for something like “python check if directory exists” .
After some trying you may look at the hint.
Generating the call information
Have your program generate the argument list needed to start a process to involve the find command.
After some trying you may look at the hint.
Making the call
Have your program actaually make the call to find.
After some trying you may look at the hint. This hint has a little hack that diverts the error messages to /dev/null for Python2. See a stackoverflow posting for more information.
After some trying you may look at the hint.
Reading the output with a pipe
This time have your program actually read from the pipe. The difference between this step and the previous is subtle.
After some trying you may look at the hint.
Getting the file size
This time print the file and its size.
Again, you can just Google for this.
However, do take a look at the Python
os module.
There is a os.stat
method that returns the same information
as the POSIX stat
function.
Be sure to click the
os.stat
link!
This is the last hint.
Finishing up
We’ve done all the process stuff. You should be able to handle it from here.