运行外部命令并获取其消耗的CPU量

时间:2012-12-15 03:39:31

标签: python

非常简单,我想在Python脚本中运行一个外部命令/程序,一旦完成,我还想知道它消耗了多少CPU时间。

硬模式:并行运行多个命令不会导致CPU消耗结果不准确。

5 个答案:

答案 0 :(得分:10)

在UNIX上:要么(a)使用resource模块(也请参阅icktoofay的回答),或者(b)使用time命令并解析结果,或者(c)使用/proc文件系统,解析/ proc / [pid] / stat并解析utimestime个字段。其中最后一个是特定于Linux的。

使用resource

的示例
import subprocess, resource
usage_start = resource.getrusage(resource.RUSAGE_CHILDREN)
subprocess.call(["yourcommand"])
usage_end = resource.getrusage(resource.RUSAGE_CHILDREN)
cpu_time = usage_end.ru_utime - usage_start.ru_utime

注意:没有必要执行fork / execvp,subprocess.call()或其他subprocess方法在这里很好用,并且更容易使用。

注意:您可以使用subprocess.Popen或subprocess.call和threads同时从同一个python脚本运行多个命令,但资源不会返回正确的个别cpu次数,它将返回它们之间的时间总和呼唤getrusage;为了获得单独的时间,每个命令运行一个小的python包装器,如上所述计时(可以从主脚本启动它们),或使用正确工作的time方法多个同步命令(时间基本上只是这样一个包装器)。

使用time

的示例
import subprocess, StringIO
time_output = StringIO.StringIO()
subprocess.call(["time", "yourcommand", "youroptions"], stdout=time_output)
# parse time_output

在Windows上:您需要以某种方式使用性能计数器(也称为“性能数据助手”)。这是底层API的C example。要从python中获取它,您可以使用以下两个模块之一:win32pdh(pywin32的一部分; sample code)或pyrfcon(跨平台,也适用于Unix; {{3} })。

这些方法中的任何一种实际上都满足上述“硬模式”要求:即使在繁忙系统上有多个不同进程的运行实例,它们也应该是准确的。与在空闲系统上仅运行一个进程相比,它们可能无法产生完全相同的结果,因为进程切换确实有一些开销,但它们将非常接近,因为它们最终从OS调度程序获取数据。

答案 1 :(得分:4)

在可用的平台上,the resource module可能会提供您所需的内容。如果需要同时计时多个命令,则可能需要(对于要运行的每个命令)fork,然后创建子进程,以便仅获取该进程的信息。这是你可以这样做的一种方式:

def start_running(command):
    time_read_pipe, time_write_pipe = os.pipe()
    want_read_pipe, want_write_pipe = os.pipe()
    runner_pid = os.fork()
    if runner_pid != 0:
        os.close(time_write_pipe)
        os.close(want_read_pipe)
        def finish_running():
            os.write(want_write_pipe, 'x')
            os.close(want_write_pipe)
            time = os.read(time_read_pipe, struct.calcsize('f'))
            os.close(time_read_pipe)
            time = struct.unpack('f', time)[0]
            return time
        return finish_running
    os.close(time_read_pipe)
    os.close(want_write_pipe)
    sub_pid = os.fork()
    if sub_pid == 0:
        os.close(time_write_pipe)
        os.close(want_read_pipe)
        os.execvp(command[0], command)
    os.wait()
    usage = resource.getrusage(resource.RUSAGE_CHILDREN)
    os.read(want_read_pipe, 1)
    os.write(time_write_pipe, struct.pack('f', usage.ru_utime))
    sys.exit(0)

然后您可以使用它来运行一些命令:

get_ls_time = start_running(['ls'])
get_work_time = start_running(['python', '-c', 'print (2 ** 512) ** 200'])

执行该代码后,这两个命令应该并行运行。如果您想等待它们完成并获得执行时间,请调用start_running返回的函数:

ls_time = get_ls_time()
work_time = get_work_time()

现在ls_time将包含执行时间lswork_time将包含执行时间python -c "print (2 ** 512) ** 200"

答案 2 :(得分:3)

你可以在Python中做时间,但是如果你想知道程序的整体CPU消耗,那就太愚蠢了。最好的办法就是使用GNU time程序。它甚至是大多数操作系统的标准配置。

答案 3 :(得分:1)

您可以使用ipython的%time magic function

执行此操作
In [1]: time 2**128
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.00
Out[1]: 340282366920938463463374607431768211456L

In [2]: n = 1000000

In [3]: time sum(range(n))
CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
Wall time: 1.37
Out[3]: 499999500000L

答案 4 :(得分:1)

python的timeit模块对于基准测试/分析非常有用。除此之外,您甚至可以从命令行界面调用它。要对外部命令进行基准测试,您可以这样:

>>> import timeit
>>> timeit.timeit("call(['ls','-l'])",setup="from subprocess import call",number=1) #number defaults to 1 million
total 16
-rw-rw-r-- 1 nilanjan nilanjan 3675 Dec 17 08:23 icon.png
-rw-rw-r-- 1 nilanjan nilanjan  279 Dec 17 08:24 manifest.json
-rw-rw-r-- 1 nilanjan nilanjan  476 Dec 17 08:25 popup.html
-rw-rw-r-- 1 nilanjan nilanjan 1218 Dec 17 08:25 popup.js
0.02114391326904297

最后一行是返回的执行时间。这里,timeit.timeit()的第一个参数是调用外部方法的代码,setup参数指定在时间测量开始之前运行的代码。 number参数是您希望运行指定代码的时间,然后您可以将number返回的时间除以获得平均时间。

您还可以使用timeit.repeat()方法,该方法采用与timeit.timeit()类似的参数,但需要额外的repeat参数来指定应调用的时间timeit.timeit()并返回每次运行的执行时间列表。

注意timeit.timeit()方法返回的执行时间是挂钟时间,而不是CPU时间。因此,其他过程可能会干扰时间。因此,在timeit.repeat()的情况下,您应该采用最小值而不是尝试计算平均值或标准差。