Our series of Python examples continues! If you’ve missed our previous posts, we have some tutorials in parts one and two, tips on setting up Python and Eclipse, cluster submission guides, and so forth.
Matt has been helping me get up to speed using Python. He always told me that some processes are a lot easier in Python than in C++, and I suppose I didn’t believe him til recently. Here is my first shot at a Python program that’s all my own, and I wanted to share it with you here. The code is below, then some comments follow. The group has recently begun several GitHub code repositories! You can link to this code sample at my repository.
import re import os import sys import time from subprocess import Popen from subprocess import PIPE LINE_BUFFERED = 1 def main(): #Define the command that you would like to run through the pipe. This will typically be your #executable set up to work with MOEAframework, and associated arguments. Specifically here #we are working with the LRGV problem. cmd = ['./lrgvForMOEAFramework', '-m', 'std-io', '-c', 'combined', '-b', 'AllDecAll'] #Verify the command print "The command to run is: %s" % cmd #Use popen to open a child process. The standard in, out, and error are sent through a pipe. child = Popen(cmd, cwd='//home//joka0958//re-evaluator_2013-04-05//', bufsize=LINE_BUFFERED, stdin=PIPE, stdout=PIPE, stderr=PIPE) #The current version of the model spits out some lines to the console when it initializes them. #When using this python child process, we need to intentionally send and receive all output (i.e. it doesn't #automatically do it for us. Here there are 3 initialization lines to catch: print "Reading initializer lines." for i in range(0,3): line = child.stdout.readline() if line: print line else: raise Exception("Evaluator died!") #Now we want to step through an existing Borg output file, which already contains decision variables and objectives. #We are going to step through each line, read in the decision variables from the file, and then evaluate those decision #variables in our external program. myFilename = "AllDecAllExperimentData.txt" fp = open(myFilename, 'rb') for line in fp: if "#" in line: #This "if" statement is helpful if you want to preserve the generation separators and header lines that appeared #in the original file. print line else: #Read in all the variables on the line (this is both decisions and objectives) allVariables = [float(xx) for xx in re.split("[ ,\t]", line.strip())] #Only keep what you want variables = allVariables[0:8] #We want to send the decision variables, separated by a space, and terminated by a newline character decvarsAsString = '%f %f %f %f %f %f %f %f\n' % (variables, variables, variables, variables, variables, variables, variables, variables) #We send that string to the child process and catch the result. print "Sending to process" child.stdin.write(decvarsAsString) child.stdin.flush() #you flush, so that the program knows the line was sent #Now obtain the program's result print "Result:" outputLine = child.stdout.readline() print outputLine #Since this is in a loop, it will operate for every line in the input file. if __name__ == "__main__": main()
Basically, your child process gets created in the beginning of this script. It is hanging out, waiting for input. The cool thing about the way input and output is handled here, is that you have complete control over what gets sent to the child program and what gets read in from it. Also, you can send multiple solutions to the program, and read their output sequentially.
Python also gives you lots of great control over input and output formatting in a relatively simple fashion. Notice how we are moving back and forth from strings and floats effortlessly. I also like how the control sequences (for loops, if else statements) are very straightforward and easy to read.
Feel free to adapt this code for your own purposes, and provide comments below!