Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 同时启动两个bash命令,并从先前完成的进程中收集结果_Python_Subprocess - Fatal编程技术网

Python 同时启动两个bash命令,并从先前完成的进程中收集结果

Python 同时启动两个bash命令,并从先前完成的进程中收集结果,python,subprocess,Python,Subprocess,假设我想从Python脚本中运行两个bash命令c1和c2,它们基本上在Linux上处理(但不修改)同一段数据(因此这不是微妙的竞争条件) 现在我想同时启动它们(使用os.system),看看哪一个更快完成,一旦一个进程完成,我将收集其输出(可以转储到带有c1>>log1.txt的文件中),并终止另一个进程 请注意,两个进程的处理时间可能会有很大差异,因此可以观察到,例如一个进程需要10秒,而另一个进程需要60秒 不使用线程的方法可能类似于: import os, subprocess, tem

假设我想从Python脚本中运行两个bash命令
c1
c2
,它们基本上在Linux上处理(但不修改)同一段数据(因此这不是微妙的竞争条件)

现在我想同时启动它们(使用
os.system
),看看哪一个更快完成,一旦一个进程完成,我将收集其输出(可以转储到带有
c1>>log1.txt的文件中),并终止另一个进程


请注意,两个进程的处理时间可能会有很大差异,因此可以观察到,例如一个进程需要10秒,而另一个进程需要60秒

不使用线程的方法可能类似于:

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)

请注意,我们仍然没有使用
os.system()
,也没有使用
shell=True
wait-n
是一个bash扩展,因此我们需要确保bash(而不是
/bin/sh
)可供其运行。

一种不使用线程的方法可能类似于:

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)

请注意,我们仍然没有使用
os.system()
,也没有使用
shell=True
wait-n
是一个bash扩展,因此,我们需要确保bash——而不是
/bin/sh
——能够正常工作。

您的问题是什么?我们能否在您的代码中找到一个峰值:)这听起来像是您的处理脚本出现了一个丑陋的问题,您正试图用一个更丑陋的解决方法来修复它。描述你真正的问题
os.system()
是错误的工具。使用
subprocess.Popen()
,这样每个进程都会返回一个单独的Python对象,您可以分别轮询或等待进程(有超时,以允许在不将程序置于占用整个CPU核心的繁忙循环中的情况下检查这两个进程)。除此之外,我们还需要一个足够具体的解决方案。你的问题是什么?我们能在你的代码上有一个峰值吗:)听起来你的处理脚本有一个丑陋的问题,你正试图用一个更丑陋的解决方法来修复它。描述你真正的问题
os.system()
是错误的工具。使用
subprocess.Popen()
,这样每个进程都会返回一个单独的Python对象,您可以分别轮询或等待进程(有超时,以允许在不将程序置于占用整个CPU核心的繁忙循环中的情况下检查这两个进程)。除此之外,我们还需要一个足够具体的解决方案。