System Administration — Notes on Python

The starter

What was needed for the Python prep assignment?

A lot

And maybe even more

References for the harder stuff

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:

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.