views:

443

answers:

2

I would like to use python to make system calls to programs and time them. From the Linux command line if you type:

$ time prog args

You get something along the lines of:

real    0m0.110s
user    0m0.060s
sys     0m0.024s

if you do a 'man time', it states that you can type:

$ time -f "%E" prog args

in order to format to get only display the elapsed time. This does not work in the shell. I beleive it doesn't work because bash must have its own time function. If you type:

$/usr/bin/time -f "%E" prog args

you get the expected output as stated in the man pages.

I want the bash time because it seems to be more accurate. My problem is, when you try to use the 'time prog args' command from python, it doesn't behave the same way as when you type it in.

Code below to see what I'm doing (Please excuse the sloppiness):

#!/usr/bin/env python
"""Quick & Dirty script to time program execution for multiple inputs.
Saves the results as a .csv for importing into excel."""
import subprocess
timing = 'time -f "%E" '
program = 'java smartfib '
filename = 'smarttimes.csv'
#arglist = [0, 10, 20, 30, 31, 32, 33, 34, 35]
#arglist = [0, 2, 3, 5]
arglist = range(50)
timelist = list()

#run the program with the specified input values
for arg in arglist:

    cmd = timing + program + str(arg)
    pipe = subprocess.Popen(cmd, shell = True, bufsize = 256,
       stderr = subprocess.PIPE, stdout = subprocess.PIPE)

    [answer,times] = pipe.communicate() #read from pipe
    #print times
    if(int(answer) < 0):
     print "overflow occured at fib(%d)!\n" %arg
     break
    #save (n, [time it takes to complete] as a tuple in a list)
    timelist.append([arg,times])


csv = list() #list for formatted comma separated values for excel
for item in range(len(timelist)):
    csv.append(
     str(timelist[item][0]) + "," + timelist[item][1][2:].strip('\n')
     )

results = file(filename,'w')
results.write('n,time(in s)\n')
for item in range(len(csv)):
    results.write(csv[item]+'\n')

results.close()

def getTimeInSeconds(self, timestring):
    pass
+2  A: 

You are correct that bash has it's own version of time.

$ type time
time is a shell keyword

Perhaps you could explicitly invoke bash with the -c option to get it's timing.

Depending on which distribution you're using, the default shell may be dash, a simpler shell that doesn't have time as a keyword. Both Debian and Ubuntu use dash but I don't know what Red Hat, Fedora and others use.

David Locke
yes this was the problem. I didn't use a -c option, but I specified that I wanted to use bash when I open the pipe.
Derrick
A: 

I don't think time will be more accurate than Pythons methods, unless you use os.times() in versions below 2.5.3, and look at the user time, because earlier versions of Python has a big there.

And although the time command behaves differently then bash's time builtin, they both return the relevant information, so I'm unclear on what the problem is, really.

Lennart Regebro
Using the os.times() is an option, but I'd like to avoid that because it would include the time it takes for python to go off and ask the system for resources. Im pretty sure the cost of the context switch for python is bigger than the bash time function. This doesn't rule out using os.times(), but I'd prefer the other way.
Derrick
Bigger than asking python to fork a process, and start time, and you read in and parse those results? That seems highly unlikely. In fact, a quick test shows that os.times() will be at LEAST 1000 times faster.
Lennart Regebro
os.times() would be beneficial if I was only timing python stuff. But I was timing python, C and java to name a few. So os.times() would start counting, then go off and fork a process in the other language then come back and stop counting. The time python takes to parse the timing info from bash wouldnt matter because when it gets that info from bash, its already done counting. Ussing os.times() to time a python program/function would give an unfair advantage over other languages.
Derrick
Aha, you want to time and external process from python, got it.
Lennart Regebro