如何运行两个python子进程并获取运行时和stdout,stderr?

时间:2012-02-23 20:02:13

标签: python multithreading multiprocessing subprocess

我正在考虑在一台机器上同时运行两个子进程,以便我可以获得准确的运行时。我正在比较两个版本的软件并对它们运行诊断,例如运行时,输出变化等。

最初我有一个功能,它在同一输入文件中使用两个版本的软件,每个输出到不同的地方。旧版本和新版本通过argparser获取。该函数对每个软件命令使用一个子进程,然后通过.communicate()获取输出。但我知道.communicate()等待进程完成,理想情况下我想同时在两个进程上使用.communicate(),以便它们同时启动,并且是定时的,并且每次都会给我结果只要我知道他们的运行时间。

我的问题,更简洁的是,我如何运行两个子进程,每个子进程单独运行并同时启动。然后抓住他们的运行时和stdout,stderr?

下面是我的函数的一个快速示例(只是假装我在某些文件上测试java的速度):

def test():
    # Get start time        
    before = time.time()
    cmd1 = ['java-1.0', 'blah']
    c1 = subprocess.Popen(cmd1, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    cmd2 = ['java-1.5', 'blah']
    c2 = subprocess.Popen(cmd2, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    # Start both processes at the same time??
    results = [c1.communicate(), c2.communicate()]
    # Get total time taken
    total = round(time.time()-before, 2)
    # Print out the total time (I know its messy but its accurate)
    print "%s:%s:%s" % (int(total/60/60), int(total/60), int(total))
    c1.stderr.close()
    c2.stderr.close()
    return results

我想要做的另一点是我需要它们同时运行,因为如果我在一台功能强大的远程计算机上运行一个作业(我将会这样做),那么我需要在运行时保持工作负载相同这样的工作只是因为一个进程在不同的时间运行而没有更快地完成。

3 个答案:

答案 0 :(得分:0)

如果您尝试获得准确的运行时,则需要多次运行测试并查看分布 - 中位运行时应该是一个很好的指标。同时运行它们不会帮助您获得更准确的结果。

答案 1 :(得分:0)

运行时测试通常在空闲机器上完成,并且在有和没有不同输入文件的情况下重复几次,以了解操作系统缓存的影响。

让两个进程竞争相同的资源将导致更准确的测量。

加速Python程序通常是使用正确工具的情况。例如。列表和其他理解通常比循环更快。使用内置函数可能胜过它。一个很好的例子是“an optimization anecdote”。可能最好的优化是不同的算法。

使用PyPy代替CPython也可能会带来显着的改进。

答案 2 :(得分:0)

在这种情况下,由于您没有要发送到流程的输入,因此您无需使用Popen.communicate()。 Popen调用本身就开始了这个过程,我们不需要Popen.communicate()。您可以使用Popen.poll()检查进程是否已完成,而不是使用Popen.communicate()。

while True:
    if c1.poll() is not None:
        #Stop c1's timer
    if c2.poll() is not None:
        #Stop c2's timer

如果你想要stdout和stderr,你可以产生2个线程,然后使用Popen.communicate()并记录时间。

你可以使用这样的东西作为一个线程:

def time_it(c):
    results.append(c.communicate())
    times.append(time.time())

要生成线程,请调用

results = []
times = []
threading.start_new_thread(time_it,(c1,))
threading.start_new_thread(time_it,(c2,))
相关问题