如何查找多个子进程的执行时间?

时间:2018-05-26 18:56:55

标签: python linux python-3.x time subprocess

我有一个Linux命令列表,我正在使用子进程模块运行每个命令,我需要弄清楚如何找到每个命令的执行时间并在列表或字典中返回执行时间,在dict的情况下,Key可以是命令名称,值是以秒为单位的时间。

即。 (Popen object).poll() == 0完成的那一刻应确定完成时间。

我正在使用 Python 3.5.2

例如:

import time
import shlex
from subprocess import *`

#list of commands
commands = ['sleep 5', 'ls -l', 'find /usr','sleep 3','uptime']

#executing each command in the list
for command in commands:
     cmd = shlex.split(command)
     # Need to time this and the moment it is finished executing.
     x = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)

应该返回/打印:

- Commands   Time(secs)
- sleep 5     5.0004   #whatever the time it takes
- ls -l       0.000    #and so on....

2 个答案:

答案 0 :(得分:1)

Popen是穷人"在后台奔跑"技术。您可以控制该过程,但如果您想等待它以非轮询方式结束,则不能。

如果你不关心输出,只关心执行时间,你可以在一个线程中包装每个subprocess.call(不再需要Popen),并更新一个字典命令= >花费的时间

启动线程不会阻塞,但call阻止,让您更轻松地执行时间。

import threading,time,subprocess,shlex

time_dict = {}

def time_me(command):
    start_time = time.time()
    cmd = shlex.split(command)
    subprocess.call(cmd)
    time_dict[command] = time.time() - start_time

threads = []
commands = ['sleep 5', 'ls -l', 'find /usr','sleep 3','uptime']

for command in commands:
    t = threading.Thread(target=time_me,args=(command,))
    t.start()
    threads.append(t)

for t in threads:
    t.join()

print(time_dict)

答案 1 :(得分:1)

虽然线程肯定是解决此问题的方法(假设正确处理共享数据),但您也可以运行while循环:

import time
import shlex
from subprocess import *

#list of commands
commands = ['sleep 5', 'ls -l', 'sleep 3', 'uptime', 'find /usr']
times = {}
running = {}
#executing each command in the list
for command in commands:
    start_time = time.time()
    cmd = shlex.split(command)
    times[command] = time.time()
    running[command] = Popen(cmd,
                             # no shell=True, shlex already did the split
                             stdout=PIPE, stderr=PIPE)

while len(running):
    finished = set()
    for cmd, proc in running.items():
        if proc.poll() is not None:
            times[cmd] = time.time() - times[cmd]
            finished.add(cmd)
        else:
            proc.communicate() # drain the pipe

    for cmd in finished:
        del running[cmd]

print(times)

请注意,这不会阻止(与其线程替代相反),因此最终可能会占用您的CPU。为了减轻负担,您可以在循环结束时添加对time.sleep的调用,使结果稍微不准确。

编辑: 由于您在示例中使用了管道,因此我假设您希望使用(某些)命令的输出进行一些有意义的处理。无论您是否愿意,如果您不执行proc.communicate,您将最终填满管道,从而阻止该过程。或者,您当然可以重定向输出(到某个文件或/ dev / null)。与流程进行通信也可能会改变结果,处理也是如此:)