17.2. Running Programs

You can run external programs from a Python program. There are three major tasks to perform in order to run programs from a script:

Example 17.2. Running a program (1)

The simplest way to run a program is by using the system of the os module. The result of the program will be printed on the standard output, which is normally the screen. The return value reports about the success or failure of the execution.
import os
cmd="golden swissprot:malk_ecoli"
status = os.system(cmd)
print "Status: ", status
	    
Another Python module, commands, enables to store the result of the execution in a string:
import commands
cmd="golden swissprot:malk_ecoli"
output = commands.getoutput(cmd)
print "Output: ", output
	    
To get both result and status:
import commands
cmd="golden swissprot:malk_ecoli"
status, output = commands.getstatusoutput(cmd)
print "Output: ", output
print "Status: ", status
	    

Example 17.3. Running a program (2)

A more elaborate but lower level interface to run commands is provided by the popen function from the os module. The following script runs a program that fetches a Swissprot entry given its entry name, and prints it on the screen.
import os
import string
cmd="golden swissprot:malk_ecoli"                                         (1)
handle = os.popen(cmd, 'r')                                               (2)
print string.join(handle.readlines())                                     (3)
handle.close()
	    
1

Builds the command line with a program name and the arguments.

2

Runs the command and stores a handle in the handle variable. A handle for a command is the same kind of objects as a file handle: you open it (with the popen command, read from it, and close it.

3

Reads all the lines from the handle, and prints the joint result.

If the program takes time and if you wish to read the result step by step as long as results show up, you can do like this:
import os
import sys

cmd="blastall -i " + sys.argv[1] + " -p blastp -d swissprot"
handle = os.popen(cmd, 'r', 1)
for line in handle:
    print line,
handle.close()
	    
What if the entry name does not have a corresponding entry in the database? Let us try the following code:
import os
import sys
import string
cmd="golden swissprot:" + sys.argv[1]                                     (1)
handle = os.popen(cmd, 'r')
print string.join(handle.readlines())
status = handle.close()
if status is not None:
    print "An error occured: ", status                                    (2)
	    
1

Takes the entry name from the Python command line arguments, by using the sys module argv variable.

2

If the provided entry name is invalid, the program returns a non zero value, that is returned by the close function.

If you wish to get the complete error message from the program, use the popen3 function:
import os
import sys
cmd="golden swissprot:" + sys.argv[1]
tochild, fromchild, childerror = os.popen3(cmd, 'r')
err = childerror.readlines()
if len(err) > 0:
     print err
else:
     print fromchild.readlines()
	    
In this script, the call returns three objects: one to get results: fromchild (standard output), one to write to the program - on its standard input - (for instance when the program is prompting for a value (see Example 17.4): tochild, and one to access to the standard error file descriptor of the program.

Example 17.4. Running a program (3)

The next example shows how to run an interactive program, both reading the output and writing on the standard input to answer program's questions. The Phylip dnapars program, once having read the input file containing an alignment, that is always called infile, waits for the user to enter 'y' and 'Return' to proceed. The following script runs dnapars after some file cleaning.
import popen2
import os.path

cmd = "dnapars"

if os.path.exists('treefile'):                                            (1)
    os.unlink('treefile')
if os.path.exists('outfile'):
    os.unlink('outfile')

child = popen2.Popen3(cmd)                                                (2)
print "PID: ", child.pid
child.tochild.write("y\n")                                                (3)
child.tochild.close()
child.wait()                                                              (4)
print "".join(child.fromchild.readlines())                                (5)
status = child.fromchild.close()
if status is not None:
    print "status: ", status
	    
1

Removes old dnapars output files.

2

Use of the class Popen3 that stores the information about the run program. The return value: child, is an object representing the "child" processus, that has attributes to get the channels to communicate with the processus: a handle to write to the standard input of the processus (child.tochild), and a handle to read its output (child.fromchild). See Chapter 18 for more informations on classes.

3

Answers to program prompt.

4

This statements helps in cleaning the processus after completion.

3

Reads results.