4

我想测量我的 Python 脚本使用其输出的外部程序的执行时间。

调用extprogram产生输出的程序,此刻我做了类似的事情:

import time
import subprocess

def process_output(line):
   ...
   ...
   return processed_data

all_processed_data = []

ts = time.time()
p = subprocess.Popen("extprogram", stdout=subprocess.PIPE)

for line in p.stdout:
    all_processed_data.append(process_output(line))
te = time.time()
elapsed_time = te - ts

这不能按预期工作,因为我测量的是执行时间extprogram加上处理其输出所需的时间。

extprogram产生大量数据,因此我想像现在一样使用循环将其输出“流式传输”到我的 Python 程序中。如何评估te何时extprogram终止而不是等待处理所有输出?

4

2 回答 2

1

以下仍然使用“挂钟”时间,但可能是使用主机系统时间命令的替代方法。执行和计时被分成单独的线程,并且可以在执行任何处理之前停止计时器。

from multiprocessing import Event
import threading
import time
import subprocess

def timing(event):
    print "timer starts"
    ts = time.time()
    event.wait()
    te = time.time()
    elapsed_time = te - ts
    print "Elapsed Time " + str(elapsed_time)

def execution(event): 
    for i in range(0,1000):
        p = subprocess.Popen("ls", stdout=subprocess.PIPE)
    event.set()

if __name__ == '__main__':  
    event = Event()
    e = threading.Thread(target=execution, args=(event,))
    t = threading.Thread(target=timing, args=(event,))
    t.start()  
    e.start() 
    while not event.is_set():
        print "running..."
        time.sleep(1)

这给了我以下输出:

timer starts
running...
running...
Elapsed Time 1.66236400604

或者您可以从输出处理中拆分接收“extprogram”的输出。

例如:

ts = time.time()
p = subprocess.Popen("extprogram", stdout=subprocess.PIPE)

for line in p.stdout:
    tempdata.append(line)

te = time.time()
elapsed_time = te - ts

for line in tempdata:
    all_processed_data.append(process_output(line))
于 2013-04-03T12:51:08.110 回答
1

由于您在 Unix 下,您可以使用该time命令。这里是原理:

import sys
import subprocess

p = subprocess.Popen(["time", "ls"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

for line in p.stdout:  # ls output
    sys.stdout.write(line)

time_output = p.stderr.readlines()

print "Stderr:", ''.join(time_output)

在我的机器上,这给出了:

Stderr:         0.01 real         0.00 user         0.00 sys

总处理器时间为user+sys时间(real是挂钟时间,一般不代表程序使用了多少处理器时间:例如 with sleep 5real时间为 5 秒,而userandsys时间为 0)。

这是有效的,因为time输出了对实际执行时间的详细说明(不仅仅是墙上时间,这取决于正在运行的其他进程等),并且对标准错误输出这样做。您可以解析标准错误并获取时间信息。

如果您将数据输出到可能会干扰time命令解析的标准错误,则此方法可能不实用。

另外,我还没有检查上面的代码不会发生死锁(我不确定如果调用的程序对标准错误打印很多会发生什么:程序是否会阻塞,直到读取标准错误缓冲区,这如果 Python 程序正在读取标准输出,可能不会发生?)。也就是说,如果你知道定时程序没有或很少有关于标准错误的数据,我相信上面的代码不会死锁。

于 2013-04-03T13:26:05.443 回答