假设我想从我的Python脚本中运行两个bash命令c1
和c2
,它们实际上在Linux上处理(但不修改)相同的数据(因此这不是微妙的竞争条件) )。
现在,我想同时启动它们(使用os.system
),看看哪一个更快完成,一旦一个进程完成,我将收集其输出(可以与{{1转储到文件中}}),然后终止其他过程。
请注意,两个过程的处理时间可能会有很大差异,因此可以观察到,例如一个过程需要十秒钟,而另一个过程则需要60秒。
答案 0 :(得分:2)
一种无需线程即可工作的方法可能类似于:
import os, subprocess, tempfile
def get_first_outfile(inputFileName):
p1_stdout = tempfile.NamedTemporaryFile()
p2_stdout = tempfile.NamedTemporaryFile()
p1 = subprocess.Popen(['process-one', inputFileName], stdout=p1_stdout)
p2 = subprocess.Popen(['process-two', inputFileName], stdout=p2_stdout)
while True:
if p1.poll() is not None: # Process 1 finished first
(file_keep, file_kill) = p1_stdout, p2_stdout
(proc_keep, proc_kill) = p1, p2
break
if p2.poll() is not None: # Process 2 finished first
(file_keep, file_kill) = p2_stdout, p1_stdout
(proc_keep, proc_kill) = p2, p1
break
time.sleep(0.1) # Wait to poll again
proc_kill.terminate() # Terminate the process that didn't finish
file_keep.seek(0) # Rewind the output file we want to keep to the beginning
file_kill.close() # closing a tempfile deletes it
if finished_first.returncode != 0:
raise Exception("Process failed with status %r" % finished_first.returncode)
return keep_outfile # Return the output file we want to keep
或者,可以让Python调用shell并在那里进行工作:
shellScript = '''
outOne=$(mktemp -t out.XXXXXX) || exit
outTwo=$(mktemp -t out.XXXXXX) || exit
processOne "$@" >"$outOne" & proc1_pid=$!
processTwo "$@" >"$outTwo" & proc2_pid=$!
wait -n # wait for one of the two processes to finish
if kill -0 "$proc1_pid"; then
# proc1 is still running, so proc2 finished
cat -- "$outTwo"
kill "$proc1_pid"
else
cat -- "$outOne"
kill "$proc2_pid"
fi
'''
def get_output_from_first_process(inputFileName):
return subprocess.check_output(['bash', '-c', shellScript, '_', inputFileName],
stdout=subprocess.PIPE)
请注意,我们 still 并未使用os.system()
,而也是并未使用shell=True
:wait -n
是一个bash扩展,因此我们需要确保bash而不是/bin/sh
可用。