非常简单,我想在Python脚本中运行一个外部命令/程序,一旦完成,我还想知道它消耗了多少CPU时间。
硬模式:并行运行多个命令不会导致CPU消耗结果不准确。
答案 0 :(得分:10)
在UNIX上:要么(a)使用resource模块(也请参阅icktoofay的回答),或者(b)使用time命令并解析结果,或者(c)使用/proc文件系统,解析/ proc / [pid] / stat并解析utime
和stime
个字段。其中最后一个是特定于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
将包含执行时间ls
,work_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()
的情况下,您应该采用最小值而不是尝试计算平均值或标准差。