As part of an evaluation, I want to measure and compare the user+system runtime of different diff-tools.
As a first approach, I thought about calling the particular tools with time - f
(GNU time
). Since the rest of the evaluation is done by a bunch of Python scripts I want to realise it in Python.
The time output is formatted as follows:
<some error message>
user 0.4
sys 0.2
The output of the diff tool is redirected to sed
to get rid of unneeded output and the output of sed
is then further processed. (use of sed
deprecated for my example. See Edit 2)
A call from within a shell would look like this (removes lines starting with "Binary"):
$ time -f "user %U\nsys %S\n" diff -r -u0 dirA dirB | sed -e '/^Binary.*/d'
Here is my approach so far:
import subprocess
diffcommand=["time","-f","user %U\nsys %S\n","diff","-r","-u0","testrepo_1/A/rev","testrepo_1/B/rev"]
sedcommand = ["sed","-e","/^Binary.*/d"]
# Execute command as subprocess
diff = subprocess.Popen(diffcommand, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
# Calculate runtime
runtime = 0.0
for line in diff.stderr.readlines():
current = line.split()
if current:
if current[0] == "user" or current[0] == "sys":
runtime = runtime + float(current[1])
print "Runtime: "+str(runtime)
# Pipe to "sed"
sedresult = subprocess.check_output(sedcommand, stdin=diff.stdout)
# Wait for the subprocesses to terminate
diff.wait()
However it feels like that this is not clean (especially from an OS point of view). It also leads to the script being stuck in the readlines
part under certain circumstances I couldn't figure out yet.
Is there a cleaner (or better) way to achieve what I want?
Edit 1 Changed head line and gave a more detailed explanation
Edit 2
Thanks to J.F. Sebastian, I had a look at os.wait4(...)
(information taken from his answer. But since I AM interested in the output, I had to implement it a bit different.
My code now looks like this:
diffprocess = subprocess.Popen(diffcommand,stdout=subprocess.PIPE)
runtimes = os.wait4(diffprocess.pid,0)[2]
runtime = runtimes.ru_utime + runtimes.ru_stime
diffresult = diffprocess.communicate()[0]
Note that I do not pipe the result to sed
any more (decided to trim within python)
The runtime measurement works fine for some test cases, but the execution gets stuck sometimes. Removing the runtime measurement then helps the program to terminate and so does sending stdout
to DEVNULL
(as demanded here). Could I have a deadlock? (valgrind --tool=helgrind
did not find anything) Is there something fundamentally wrong in my approach?