tags:

views:

262

answers:

4

Hi,

I’ve a bash script I’ve been using for a Linux environment but now I have to use it on a Windows platform and want to convert the bash script to a python script which I can run.

The bash script is rather simple (I think) and I’ve tried to convert it by google by way around but can’t convert it successfully.

The bash script looks like this:

runs=5

queries=50

outfile=outputfile.txt

date  >> $outfile


echo -e "\n---------------------------------"
echo -e "\n----------- Normal --------------"
echo -e "\n---------------------------------"
echo -e "\n----------- Normal --------------" >> $outfile
for ((r = 1; r < ($runs + 1); r++))
do
    echo -e "Run $r of $runs\n"

    db2 FLUSH PACKAGE CACHE DYNAMIC

    python reads.py -r1 -pquery1.sql -q$queries -shotelspec -k6 -a5 >> $outfile
done

The main command, the python read.py … etc. is another python file I’ve been given and have the arguments as you see.

I know it is a lot to ask for, but it would really help me out if someone could convert this to a python script I can use or at least give me some hints and directions.

Sincerely

Mestika

Added per request:

This is what I've written but without success:

runs=5
queries=50
outfile=ReadsAgain.txt
file = open("results.txt", "ab")

print "\n---------------------------------"
print "\n----------- Normal --------------"
print "\n---------------------------------"
file.write("\n----------- Normal --------------\n")
print "\n------------- Query without Index --------------"
file.write("\n------------- Query without Index --------------\n")
for r = 1; r < (%s + 1); r++ % runs
    print "Run %s of %s \n" % r % runs

    db2 FLUSH PACKAGE CACHE DYNAMIC

    output = python reads.py -r1 -pquery1.sql -q$queries -shotelspec -k6 -a5
    file.write(output)

file.close()
A: 

As much as I am in favor of writing in Python rather than bash, if the only reason to convert it to Python is so that you can run it on Windows, keep in mind that you can install bash on Windows and run it as is. Cygwin.com has a complete implementation of many Unix commands.

Ned Batchelder
It was my first thought to run the bash in my cygwin but the problem is that Cybwin and DB2 has trouble talking together and one of the main reasons for the bash file is to run different queries in DB2 so I can test different Indexes to optimize performance. But it would be the best solutions to do it in Cygwin if there was a solution.
Mestika
Sorry, why is cygwin bash a problem? you _can_ call non-cygwin executables from the cygwin bash shell, you will just need to know the cygwin path, even then i know cygwin can do some windows to cygwin path conversion. For example you could call /cygdrive/c/programfiles/db2 , assuming of course that you have a non-cygwin db2 implementation that you want to use. Additionally , you can even call the windows python interpreter to run your script instead of the one listed (but I've had problems running terminal python scripts using the windows executable from within the cygwin env)
iondiode
+2  A: 

It should be fairly simple to port your program. The only tricky part will be running the db2 command and (maybe) refactoring reads.py so that it can be called as a library function.

The basic idea is the same:

  • Setting local variables is the same.
  • Replace echo with print.
  • Replace your loop with for r in range(runs):.
  • Get the date with the datetime module.
  • Replace write to file with the file objects module.
  • Replace the call to db2 with the subprocess module.
  • You'll need to import reads.py to use as a library (or you can use subprocess).

But, as Marcelo says, if you want more help- you're best off putting in some effort of your own to ask direct questions.

Stephen
A: 

This is what I've written but without success:

runs=5
queries=50
outfile=ReadsAgain.txt
file = open("results.txt", "ab")

print "\n---------------------------------"
print "\n----------- Normal --------------"
print "\n---------------------------------"
file.write("\n----------- Normal --------------\n")
print "\n------------- Query without Index --------------"
file.write("\n------------- Query without Index --------------\n")
for r = 1; r < (%s + 1); r++ % runs
    print "Run %s of %s \n" % r % runs

    db2 FLUSH PACKAGE CACHE DYNAMIC

    output = python reads.py -r1 -pquery1.sql -q$queries -shotelspec -k6 -a5
    file.write(output)

file.close()
Mestika
Hoisted this "answer" into the main body of the original post. Just so you know, you can - and should - edit your original post to add additional information requested.
msw
...and you should delete this "answer".
Dennis Williamson
+13  A: 

Answer

Let's break it down into pieces. Especially the pieces you got wrong. :)


Assignment

outfile=ReadsAgain.txt

It should come to little surprise that you need to put quotes around strings. On the other hand, you have the luxury of putting spaces around the = for readability.

outfilename = "ReadsAgain.txt"

Variable expansion → str.format (or, the % operation)

python reads.py <snip/> -q$queries <snip/>

So you know how to do the redirection already, but how do you do the variable expansion? You can use the format method (v2.6+):

command = "python reads.py -r1 -pquery1.sql -q{0} -shotelspec -k6 -a5".format(queries)

You can alternatively use the % operator:

#since queries is a number, use %d as a placeholder
command = "python reads.py -r1 -pquery1.sql -q%d -shotelspec -k6 -a5" % queries

C-style loop → Object-oriented-style loop

for ((r = 1; r < ($runs + 1); r++)) do done

Looping in Python is different from C-style iteration. What happens in Python is you iterate over an iterable object, like for example a list. Here, you are trying to do something runs times, so you would do this:

for r in range(runs):
  #loop body here

range(runs) is equivalent to [0,1,...,runs-1], a list of runs = 5 integer elements. So you'll be repeating the body runs times. At every cicle, r is assigned the next item of the list. This is thus completely equivalent to what you are doing in Bash.

If you're feeling daring, use xrange instead. It's completely equivalent but uses more advanced language features (so it is harder to explain in layman's terms) but consumes less resources.


Output redirection → the subprocess module

The "tougher" part, if you will: executing a program and getting its output. Google to the rescue! Obviously, the top hit is a stackoverflow question: this one. You can hide all the complexity behind it with a simple function:

import subprocess, shlex
def get_output_of(command):
  args = shlex.split(command)
  return subprocess.Popen(args,
                          stdout=subprocess.PIPE).communicate()[0]
  # this only returns stdout

So:

python reads.py -r1 -pquery1.sql -q$queries -shotelspec -k6 -a5 >> $outfile

becomes:

command = "python reads.py -r1 -pquery1.sql -q%s -shotelspec -k6 -a5" % queries
read_result = get_output_of(command)

Don't over-subprocess, batteries are included

Optionally, consider that you can get pretty much the same output of date with the following:

import time
time_now = time.strftime("%c", time.localtime()) # Sat May 15 15:42:47 2010

(Note the absence of the time zone information. This should be the subject of another question, if it is important to you.)


How your program should look like

The final result should then look like this:

import subprocess, shlex, time
def get_output_of(command):
  #... body of get_output_of
#... more functions ...
if __name__ = "__main__":
  #only execute the following if you are calling this .py file directly,
  #and not, say, importing it
  #... initialization ...
  with file("outputfile.txt", "a") as output_file: #alternative way to open files, v2.5+
    #... write date and other stuff ...
    for r in range(runs):
      #... loop body here ...

Post scriptum

That must look pretty horrible when compared to the relatively simple and short Bash script, right? Python is not a specialized language: it aims to do everything reasonably well, but isn't built directly for running programs and getting the output of those.

Still, you wouldn't normally write a database engine in Bash, right? It's different tools for different jobs. Here, unless you're planning to make some changes that would be non-trivial to write with that language, [Ba]sh was definitely the right choice.

badp
I'd started writing this three hours ago and when I was pretty much done, I had a blackout :(
badp
+1 for the generosity of spirit, hard work and careful explanation, ignoring the fact that the OP hadn't taken the slightest effort to learn Python or StackOverflow (I've been guilty of the same).
msw
+1: The effort you put in just deserves it ;)
Stephen