Chapter 9. Interacting with the Operating System

Whether a program helps a user balance a checkbook, play a game, write a letter, or connect to a website, all applications share one common feature — they all reside on top of an operating system. Be it Linux, Windows, or some other operating system, most applications (including Python scripts) must interface with the computer through its operating system. As with most scripting languages such as Perl or Ruby, Python has a vast collection of modules to enable the script programmer to interface with the operating system programmatically.

This chapter examines ways to communicate with the operating system through Python. Rather than a single, large application illustrating programming techniques, we will cover many topics with various snippets of code.

The commands and modules covered in this chapter are a small subset of what is available. For complete coverage of operating system services, see the Python Reference Manual.

The chapter covers three main topic areas:

  • Generic operating system services — Many features of an operating system are shared among the systems. For example, all operating systems have some way of listing files. Python's ability to access these generic operating system services makes programs more cross-platform.

  • Windows services — Python has many features to enable developers to access Windows services, such as the Windows Registry, the Windows Event Viewer, Windows services, and more. Techniques for accessing these services are explored in depth.

  • Unix/Linux services — As with Windows, with Unix or Linux there are services specific to the operating systems, such as syslog access, password and shadow password services, and others.

Generic Operating System Services

The modules covered in this section are related to operating system services that can be used regardless of the operating system in which the script runs.

The os Module — Generic OS Services

The os module has a unique purpose. It verifies the operating system that the user is running under and then calls the OS-specific function. For example, consider a function written as follows:

os.stat

If the user is running on Unix or Linux, the stat function in the posix.stat function will be called; whereas if the user is running on Windows, then the nt.stat function will be called. This enables a program to be platform-independent.

Examples

The following sections provide some examples that demonstrate several of the features of the os module.

Example 1

In this first example, a function takes a directory as a parameter, changes to that directory, and outputs the name of the directory and its contents:

import os

def get_directory_info(dir):
    os.chdir(dir)
    current_dir = os.getcwd()
    dir_contents = os.listdir(dir)
    print ""
    print "Current directory = ", current_dir
    print "Directory contents = ", dir_contents
    print""

get_directory_info('C:\python25')
get_directory_info('C:')

The output is as follows:

Current directory =  C:python25
Directory contents =  ['DLLs', 'Doc', 'include', 'Lib', 'libs', 'python.exe',
'python25.exe', 'pythonw.exe', 'pythonw25.exe', 'tcl', 'Tools', 'w9xpopen.exe']


Current directory =  C:
Directory contents =  ['$Recycle.Bin', 'autoexec.bat', 'Boot', 'bootmgr',
'BOOTSECT.BAK', 'config.sys', 'Documents and Settings', 'EasyEclipse-for-Python-
1.2.2.2', 'hiberfil.sys', 'jim', 'MSOCache', 'pagefile.sys', 'Program Files',
'ProgramData', 'Python25', 'ruby', 'sqmdata00.sqm', 'sqmnoopt00.sqm', 'System
Volume Information', 'Users', 'Windows']

Example 2

This example uses the os.urandom() function. This function randomly generates byte data of a length indicated as a parameter to the function. On a Unix or Linux system, this will query /dev/urandom, and on Windows it will use CryptGenRandom. It can work well for cryptography or passing a unique signature from one program to another:

import os

x = os.urandom(25)
y = x
z = os.urandom(25)

print "Does x = y? ", x==y
print "Does x == z? ", x==z
print "x = ", x

The output is as follows:

Does x = y?  True
Does x == z?  False
x = 12

The time Module — Format and Manipulate System Time

The time module provides various functions related to manipulating and formatting time. The module is always available, but not all functions are available on all platforms. Implementation of some of the functions varies by operating system, so it might be helpful to consult the documentation for your particular OS.

The time value is a sequence of nine integers. The return values of gmtime(), localtime(), and strptime() also offer attribute names for individual fields. The following table indicates those attribute names and values:

Index

Attribute

Values

0

tm_year

Example, 2001

1

tm_mon

Range[1–12]

2

tm_mday

Range[1–31]

3

tm_hour

Range[0–23]

4

tm_min

Range[0–59]

5

tm_sec

Range[0–61]

6

tm_wday

Range[0–6]; Monday is 0

7

tm_yday

Range[1–366]

8

tm_isdst

0, 1, −1

Examples

The following examples show the time module in action.

Example 1

This example shows the time() method, which is a floating-point number expressed in seconds since the epoch (January 1, 1970), in UTC:

import time

raw_input("Press the [Enter] key: ")
time1 = time.time()
raw_input("Wait a few seconds, then press the [Enter] key again: ")
time2 = time.time()
difference = int(time2 - time1)

print "There were ",  difference, "seconds bettween the two choices"

The output is as follows:

Press the [Enter] key:
Wait a few seconds, then press the [Enter] key again:
There were  5 seconds bettween the two choices

Example 2

This second example shows some implementations of displaying the time. Time can be shown as a tuple or as a string, and can be formatted in many different ways. In addition, different time representations are provided for (such as local time or Greenwich Mean Time [GMT] offset time):

import time

print "GMT Time as tuple: ", time.gmtime()
print "GMT Time as string: ", time.asctime(time.gmtime())
print "Local Time as tuple: ", time.localtime()
print "Local time as string: ", time.asctime(time.localtime())
print "Formatted local time in <month day, year> format: ", 
      time.strftime("%B %d, %Y")

The output is as follows:

GMT Time as tuple:   (2008, 2, 11, 1, 10, 36, 0, 42, 0)
GMT Time as string:  Mon Feb 11 01:10:36 2008
Local Time as tuple:   (2008, 2, 10, 17, 10, 36, 6, 41, 0)
Local time as string:   Sun Feb 10 17:10:36 2008
Formatted local time in <month day, year> format:  February 10, 2008

The optparse Module — Parse Command-Line Options

The optparse module gives you convenient functions for managing command-line options. It has a built-in feature to display help if a user types a --h or --help option.

Example

The following example shows how the optparse module can create options for the user:

from optparse import OptionParser

parser = OptionParser()
parser.add_option("-n", "--name", dest="name",
                  help="print name")

(options, args) = parser.parse_args()

print "your name is ", options.name

If the user runs the program with the preceding command-line option, the following output results:

I:Applied_PythonChapter_9>python optparse-example1.py --name "Jim Knowlton"
your name is  Jim Knowlton

If the program is run with a --h option, then this is the output:

I:Applied_PythonChapter_9>python optparse-example1.py --h
Usage: optparse-example1.py [options]

Options:
  -h, --help            show this help message and exit
  -n NAME, --name=NAME  print name

The platform Module — Get Platform Information

The platform module includes both platform-specific functions and cross-platform functions. This section addresses the cross-platform capability. The platform module enables you to query for both hardware and software platform information. You can then parse the information returned and act accordingly in your script.

Example

The following example demonstrates how to query for a particular operating system and then branch the code based on the operating system in which the script is running:

import platform

if platform.system() == 'Windows':
    print "The platform is Windows"
    #put Windows-specific code here
elif platform.system() == 'Linux":
    print "The platform is Linux"
    #put Linux-specific code here

If the script is run on a Windows box, then it will return the following message:

The platform is Windows

If the script is run on a Linux box, then it will return this message:

The platform is Linux

The getpass Module — Generate and Check Passwords

The getpass module provides functionality to prompt the user for a password, and enables a script to authenticate the user based on whether the correct password was entered. It also has a function to return the login of the currently logged-in user.

Example

The following example prompts for a password and if the correct password is entered, displays the login of the currently logged-in user:

import getpass

password = getpass.getpass()

if password == "letmein":
    print("Logged in username is " + getpass.getuser())

Some Other Things You Can Do

This, of course, is just a sampling of the cross-platform operating system functionality available through Python. Here are a few other areas to look into:

  • The curses module provides access to the curses library, for portable advanced terminal handling.

  • The logging module assists in managing generic system logs.

  • The errno module enables a script to translate error codes to error descriptions.

Accessing Windows Services

The following modules reflect some popular ways to access Windows services through Python.

You'll notice there isn't any coverage of Windows UI programming here. Although it certainly can be done, such a discussion is beyond the scope of this book.

The winreg Module — Manipulate the Windows Registry

The Windows Registry is a database that contains program and system information and settings. Often it can be useful to access the Registry (to read from it or write to it) via a script. The winreg module makes this easy to do in Python.

Example

The following example queries a particular key in the Registry and outputs all the subkeys for that key:

import _winreg

explorer = _winreg.OpenKey(
    _winreg.HKEY_CURRENT_USER,
    "Software\Microsoft\Windows\CurrentVersion\Explorer")

# list values owned by this registry key
i = 0
try:
    while 1:
        name, value, type = _winreg.EnumValue(explorer, i)
        print repr(name),
        i += 1
except:
    print

The following is the output for this program:

I:Applied_PythonChapter_9>python winreg-example1.py
'ShellState' 'CleanShutdown' 'Browse For Folder Width' 'Browse For Folder Height
' 'link' 'Logon User Name'

The winsound Module

The winsound module enables a script to access the sound-playing functionality of Windows platforms. It includes functions and several built-in constants. The module enables a script to play Windows system sounds or WAV files.

Example

The following example shows how to play various sounds with the winsound module:

import winsound

print "Play Windows exit sound."
winsound.PlaySound("SystemExit", winsound.SND_ALIAS)

print "Probably play Windows default sound"
winsound.PlaySound("*", winsound.SND_ALIAS)

print "Play a message beep"
winsound.MessageBeep()

print "Play an evil laugh"
winsound.PlaySound('evil_laugh.wav',winsound.SND_FILENAME)

As shown in the preceding example, the PlaySound() function has two parameters. The first parameter contains either audio data formatted as a string, a WAV file, or nothing. Its second parameter is a constant that tells the function what to do. The following table describes the available constants.

Constant Name

Description

SND_LOOP

Play the sound repeatedly. The SND_ASYNC flag must also be used to avoid blocking. Cannot be used with SND_MEMORY.

SND_MEMORY

The sound parameter to PlaySound() is a memory image of a WAV file, as a string.

SND_PURGE

Stop playing all instances of the specified sound.

SND_ASYNC

Returns immediately, allowing sounds to play asynchronously.

SND_NODEFAULT

If the specified sound cannot be found, do not play the system default sound.

SND_NOSTOP

Do not interrupt sounds currently playing.

SND_NOWAIT

Return immediately if the sound driver is busy.

MB_ICONASTERISK

Play the SystemDefault sound.

MB_ICONEXCLAMATION

Play the SystemExclamation sound.

MB_ICONHAND

Play the SystemHand sound.

MB_ICONQUESTION

Play the SystemQuestion sound.

MB_OK

Play the SystemDefault sound.

The MessageBeep() function takes an optional parameter of audio data formatted as a string. If no parameter is given (as in the preceding example), the MB_OK sound is played.

The win32serviceutil Module — Manage Windows Services

Windows services are processes that run on a Windows desktop or a Windows server machine. They can be remotely started, stopped, restarted, and queried for status. To manage Windows services, there is the win32serviceutil module, found in Mark Hammond's win32all package.

For information on how to get the win32all package, please see Appendix A.

Example

The following example shows how to start a service, stop a service, restart a service, or get service status through Python:

import win32serviceutil, time

def service_info(action, machine, service):
    if action == 'stop':
        win32serviceutil.StopService(service, machine)
        print '%s stopped successfully' % service
        time.sleep(3)
    elif action == 'start':
        win32serviceutil.StartService(service, machine)
        print '%s started successfully' % service
        time.sleep(3)
    elif action == 'restart':
        win32serviceutil.RestartService(service, machine)
        print '%s restarted successfully' % service
        time.sleep(3)
    elif action == 'status':
        if win32serviceutil.QueryServiceStatus(service, machine)[1] == 4:
            print "%s is running normally" % service
        else:
            print "%s is *not* running" % service

machine = 'localhost'
service = 'RemoteRegistry'

service_info('start', machine, service)
service_info('stop', machine, service)
service_info('start', machine, service)
service_info('restart', machine, service)
service_info('status', machine, service)

Because this example is a little longer than the others, let's examine it section by section.

The service_info function takes an action, a machine, and a service name as parameters:

def service_info(action, machine, service):

The rest of the function is simply an if structure that performs actions on the service based on the action parameter passed in:

if action == 'stop':
        win32serviceutil.StopService(service, machine)
        print '%s stopped successfully' % service
        time.sleep(3)
    elif action == 'start':
        win32serviceutil.StartService(service, machine)
        print '%s started successfully' % service
        time.sleep(3)
    elif action == 'restart':
        win32serviceutil.RestartService(service, machine)
        print '%s restarted successfully' % service
        time.sleep(3)
    elif action == 'status':
        if win32serviceutil.QueryServiceStatus(service, machine)[1] == 4:
            print "%s is running normally" % service
        else:
            print "%s is *not* running" % service

This function could be accessed by another program by importing the module, but in this case we want to be able to run the program, so some code is added at the bottom of the program to run the function multiple times, with different parameters:

machine = 'localhost'
service = 'RemoteRegistry'

service_info('start', machine, service)
service_info('stop', machine, service)
service_info('start', machine, service)
service_info('restart', machine, service)
service_info('status', machine, service)

When the program is run, it generates the following output:

RemoteRegistry started successfully
RemoteRegistry stopped successfully
RemoteRegistry started successfully
RemoteRegistry restarted successfully
RemoteRegistry is running normally

The win32net Module — Access Windows Networking Features

The win32net module, also part of Mark Hammond's win32all library of modules, includes many functions and constants to make the management of Windows networks easier. This module enables you to add, modify, delete, enumerate, and query for users, groups, shares, servers, and networks.

Example

The following example enumerates the users, groups, shares, and servers found on a computer. In this example, it simply searches the local machine, but it could easily be modified to enable selecting and authenticating to a remote computer:

import win32net

#print users
users = win32net.NetUserEnum('localhost', 0)
print "USERS"
print "=========="
for user in users[0]:
    print user['name'] + "
"

#print groups
groups = win32net.NetGroupEnum('localhost', 0)
print "GROUPS"
print "=========="
for group in groups[0]:
    print group['name'] + "
"

#print shares
shares = win32net.NetShareEnum('localhost', 0)
print "SHARES"
print "=========="
for share in shares[0]:
    print share['netname'] + "
"

#print servers
servers = win32net.NetServerEnum(None, 100)
print "SERVERS"
print "=========="
for server in servers[0]:
    print server['name'] + "
"

As you can see, the win32net module provides functions that enable you to enumerate different network objects. It also enables you to perform other operations, such as the following:

  • Adding objects

  • Deleting objects

  • Editing object properties

  • Changing the level of information returned (verbosity)

The results returned depend entirely on the particular information found, but here is the output that resulted from running the script on my system:

I:Applied_PythonChapter_9>python win32net-example1.py
USERS
==========
Administrator
Guest
jim
jim user
__vmware_user__

GROUPS
==========
None

SHARES
==========
ADMIN$
C$
IPC$
share of jim

SERVERS
==========
JIM-PC

Some Other Things You Can Do

In addition to what has been discussed in this section, there are many more ways to integrate a Python script with Windows, including the following:

  • win32crypt to use Windows encryption to copy protect data

  • win32file to interface with Windows' file APIs

  • win32inet to interact with Internet protocols through Windows

  • wincerapi to actually write Python applications to interface with Windows CE

For more information, be sure to check out Appendix A, which will point you toward some great resources for programming with Python in Windows, including a book by Mark Hammond, the creator of the win32api library for which much of this example code is written.

Accessing Unix/Linux Services

The following examples demonstrate some ways in which Python scripts can interact with a Linux or Unix system.

These examples were run on a computer running Ubuntu Linux 7.10. However, the examples should run on any version of Unix.

The termios Module — Access Unix-Style TTY Interface

The termios module provides an interface to tty I/O control. For a complete description of these calls, see the Linux or Unix manual pages. It is only available for those Unix versions that support POSIX termios style tty I/O control. All functions in this module take a file descriptor as their first argument. This can be an integer, such as what is contained in sys.stdin.fileno(), or a file object, such as sys.stdin itself.

Example

The following example shows the termios module being used to accept a password without echoing the password to the screen, and returning the password to the caller:

def getpass(prompt = "Password: "):
    import termios, sys
    fd = sys.stdin.fileno()
    old = termios.tcgetattr(fd)
    new = termios.tcgetattr(fd)
    new[3] = new[3] & ~termios.ECHO          # lflags
    try:
        termios.tcsetattr(fd, termios.TCSADRAIN, new)
        passwd = raw_input(prompt)
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old)
    return passwd

password = getpass()
if password == "zanzibar":
       print "Let you in"
else:
       print "Access denied"

The resource Module — Manage Unix System Resources

The resource module provides a mechanism for managing and controlling the amount of resources used by a particular program. It has several functions available, and makes use of a list of constants related to system resources.

Example

The example makes use of the getrusage() function. It returns a tuple that contains 16 different data items related to system resource usage. The following table shows all the data items returned.

Index

Field

Resource

0

ru_utime

Time in user mode (float)

1

ru_stime

Time in system mode (float)

2

ru_maxrss

Maximum resident set size

3

ru_ixrss

Shared memory size

4

ru_idrss

Unshared memory size

5

ru_isrss

Unshared stack size

6

ru_minflt

Page faults not requiring I/O

7

ru_majflt

Page faults requiring I/O

8

ru_nswap

Number of swap-outs

9

ru_inblock

Block input operations

10

ru_oublock

Block output operations

11

ru_msgsnd

Messages sent

12

ru_msgrcv

Messages received

13

ru_nsignals

Signals received

14

ru_nvcsw

Voluntary context switches

15

ru_nivcsw

Involuntary context switches

Here is the entire example:

import resource

resourcelist = ['time in user mode',
'time in system mode',
'maximum resident set size',
'shared memory size',
'unshared memory size',
'unshared stack size',
'page faults not requiring I/O',
'page faults requiring I/O',
'number of swap outs',
'block input operations',
'block output operations',
'messages sent',
'messages received',
'signals received',
'voluntary context switches',
'involuntary context switches']

getresource = resource.getrusage(resource.RUSAGE_SELF)

for i, item in enumerate(resourcelist):
       print item, ": ", getresource[i]

Now let's go through the example. First, a list is created with the text for all the items:

resourcelist = ['time in user mode',
'time in system mode',
'maximum resident set size',
'shared memory size',
'unshared memory size',
'unshared stack size',
'page faults not requiring I/O',
'page faults requiring I/O',
'number of swap outs',
'block input operations',
'block output operations',
'messages sent',
'messages received',
'signals received',
'voluntary context switches',
'involuntary context switches']

Then the getrusage() function is run, and its output is assigned to the list getresource:

getresource = resource.getrusage(resource.RUSAGE_SELF)

Finally, a for loop is used to output the information to the screen in a readable way:

for i, item in enumerate(resourcelist):
       print item, ": ", getresource[i]

When the program is run, the output looks like this:

time in user mode :   0.016001
time in system mode :   0.008
maximum resident set size :  0
shared memory size :   0
unshared memory size :   0
unshared stack size :   0
page faults not requiring I/O :  733
page faults requiring I/O :   0
number of swap outs :   0
block input operations :   0
block output operations :   0
messages sent :   0
messages received :   0
signals received :   0
voluntary context switches :   1
involuntary context switches :   4

The syslog Module — Access the Unix syslog

Python's syslog module enables you to access the syslog, write log entries, and read the log.

Example

The following example enables users to choose a log priority and enter a message. It then reports the status of the attempt to write to the syslog:

import syslog

print """
Enter a number and press [Enter]:
1 - Emergency
2 - Alert
3 - Critical
4 - Error
5 - Warning
6 - Notics
7 - Info
8 - Debug
"""
choice = raw_input("")

message = raw_input("Type the log message and press [Enter]: ")

if choice == '1':
       log_priority = syslog.LOG_EMERG
elif choice == '2':
       log_priority = syslog.LOG_ALERT
elif choice == '3':
       log_priority = syslog.LOG_CRIT
elif choice == '4':
       log_priority = syslog.LOG_ERR
elif choice == '5':
       log_priority = syslog.LOG_WARNING
elif choice == '6':
       log_priority = syslog.LOG_NOTICE
elif choice == '7':
       log_priority = syslog.LOG_INFO
elif choice == '8':
       log_priority = syslog.LOG_DEBUG

try:
       syslog.syslog(log_priority, message)
       print "log entry recorded"
except:
       print "problem writing to syslog"
       raise

The first section of the program simply presents a menu so that the user can choose a log priority:

print """
Enter a number and press [Enter]:
1 - Emergency
2 - Alert
3 - Critical
4 - Error
5 - Warning
6 - Notics
7 - Info
8 - Debug
"""
choice = raw_input("")

Then the user is prompted for the message to be written to the log:

message = raw_input("Type the log message and press [Enter]: ")

Based on the user's selection, the program then assigns the log priority:

if choice == '1':
       log_priority = syslog.LOG_EMERG
elif choice == '2':
       log_priority = syslog.LOG_ALERT
elif choice == '3':
       log_priority = syslog.LOG_CRIT
elif choice == '4':
       log_priority = syslog.LOG_ERR
elif choice == '5':
       log_priority = syslog.LOG_WARNING
elif choice == '6':
       log_priority = syslog.LOG_NOTICE
elif choice == '7':
       log_priority = syslog.LOG_INFO
elif choice == '8':
       log_priority = syslog.LOG_DEBUG

Finally, the syslog is written to, and the status is returned:

try:
        syslog.syslog(log_priority, message)
        print "log entry recorded"
except:
        print "problem writing to syslog"
        raise

The commands Module — Run Commands and Get Output

The commands module enables you to run system commands and capture the status of the system and the output generated by the command. It consists of the getstatus(), getoutput(), and getstatusoutput() functions:

  • getstatus(file) — Returns the output of "ls -ld file" to a string

  • getoutput(command) — Returns the output of a command as a string

  • getstatusoutput(command) — Returns a tuple containing a status code representing the state of the system, and the output of the command

Example

Following is an example showing each of the functions in action:

import commands

print r"output of commands.getstatusoutput('ls /usr/local')"
output1 = commands.getstatusoutput('ls /usr/local')
print output1
print ""

print r"output of commands.getstatusoutput('cat /bin/junk')"
output2 = commands.getstatusoutput('cat /bin/junk')
print output2
print ""

print r"output of commands.getoutput('ls /usr/local')"
output3 = commands.getoutput('ls /usr/local')
print output3
print ""

print r"output of commands.getstatus('/usr/local')"
output4 = commands.getstatus('/usr/local')
print output4
print ""

Here is what the screen output looks like for this example:

output of commands.getstatusoutput('ls /usr/local')
(0, 'bin
etc
games
include
lib
man
sbin
share
src')

output of commands.getstatusoutput('cat /bin/junk')
(256, 'cat: /bin/junk: No such file or directory')

output of commands.getoutput('ls /usr/local')
bin
etc
games
include
lib
man
sbin
share
src

output of commands.getstatus('/usr/local')
drwxr-xr-x 10 root root 4096 2007-10-16 01:17 /usr/local

Some Other Things You Can Do

There are many, many ways to interact with a Linux/Unix system in Python. Here are some modules to check out:

  • posix enables you to access operating system functionality through the POSIX interface.

  • grp provides access to the group database.

  • pwd provides access to the password database.

  • pipes provides an interface to shell pipelines.

  • nis provides access to Sun's NIS directory (Yellow Pages).

Summary

This chapter has touched on many different techniques for interacting with the operating system. Generic operating system modules are those that can be used regardless of the operating system in which the script is run. This chapter covered the following modules:

  • The os module verifies the operating system that the user is running under, and then calls the OS-specific function.

  • The time module provides various functions related to manipulating and formatting time.

  • The optparse module gives you convenient functions to manage command-line options.

  • The platform module has platform-specific functions and cross-platform functions.

  • The getpass module provides functionality to prompt the user for a password, and enables a script to authenticate the user based on whether or not a correct password was entered.

Windows-based modules enable a script to access Windows features. This chapter covered the following Windows-based modules:

  • The winreg module enables a script to read to and write from the Windows Registry.

  • The winsound module enables a script to access the sound-playing functionality of Windows platforms.

  • The win32serviceutil module, found in Mark Hammond's win32all package, enables a Python script to manage Windows services.

  • The win32net module, also part of Mark Hammond's win32all library of modules, has many functions and constants to make management of Windows networks easier.

This chapter provided several examples demonstrating how Python scripts can interact with a Linux or Unix system:

  • The termios module provides an interface to tty I/O control.

  • The resource module provides a mechanism for managing and controlling the amount of resources used by a particular program.

  • Python's syslog module enables you to access the syslog to write log entries and read the log.

  • The commands module enables you to run system commands and capture the status of the system and the output generated by the command.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.103.96