2013-04-03 2 views
4

Я хочу измерить время выполнения внешней программы, выход которой используется моим скриптом Python.Время внешней программы, выход которой обрабатывается 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 прекращает работу, а не ждет, пока все выходные данные будут обработаны?

+1

Если вы используете Linux, есть команда 'time'. – Samizdis

+0

как бы вы это использовали в моей программе? – lucacerone

+0

Ну, нормальное использование времени - это 'время extprogram args', а выходы времени - stderr. Я предполагаю, что вы могли бы сделать что-то вроде 'p = subprocess.Popen ([" time "," extprogram "], stdout = subprocess.PIPE, stderr = subprocess.PIPE)' – Samizdis

ответ

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)) 
+0

Спасибо @StuGrey. На самом деле я не могу. Как я уже сказал, внешняя программа генерирует достаточно большой объем данных и сохранение всего содержимого в памяти не является вариантом. Даже если бы я мог, то, как вы предлагаете, измеряет время выполнения внешней программы, а также время, затрачиваемое на сохранение его содержимого в списке (хорошо, что это, вероятно, быстро, но я хотел бы объективное измерение). – lucacerone

+0

Измерение времени выполнения обычно не может выполняться со временем «настенных часов»: другие запущенные процессы могут сделать измеренное время намного дольше реального времени работы. – EOL

+0

@EOL спасибо, но на данный момент настенные часы в порядке. Вы правы, но было бы хорошо, если бы на python была функция, которая сообщает время процессора таким же образом, как команда времени в linux – lucacerone

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 время настенные часы, которые обычно не представляют, как много времени процессора, используемого программой: например, с sleep 5, время real составляет 5 секунд, а user и sys раз равны 0).

Это работает, потому что time выводит подробный отчет о реальном времени выполнения (а не просто время стены, которое зависит от того, какие другие процессы работают и т. Д.), И делает это для стандартного вывода ошибки. Вы можете проанализировать стандартную ошибку и получить информацию о времени.

Этот метод может быть непрактичным, если вы программируете выводить данные на стандартную ошибку, которая может мешать анализу команды time.

Кроме того, я не проверял, что с приведенным выше кодом не может произойти взаимоблокировка (я не уверен, что произойдет, если программа называется много печатает стандартную ошибку: может ли программа блокироваться до стандартного буфера ошибок читается, что может не произойти, если программа Python считывает стандартный вывод?). Тем не менее, если вы знаете, что запрограммированная программа не имеет или мало данных о стандартной ошибке, я считаю, что код выше не будет заторможен.

+0

Я вижу две проблемы. 1. В действительности 'extprogram' уже принимает в качестве входных данных результат другого внешнего приложения. 2. вывод времени перенаправляется на stdout, что мешает выходу extprogram – lucacerone

+0

Первая точка не проблема: вы просто подключаетесь к 'time extprogram' вместо' extprogram', и результат тот же! Что касается вашего второго момента, в действительности вывод 'time' * не * перенаправляется на стандартный вывод, поэтому никаких помех не будет (вы можете увидеть это в коде:' time_output = p.stderr.readlines() '-not' p.stdout'). – EOL

+0

спасибо, это решение может работать в этом случае. Но, вообще говоря, другого пути нет? Я имею в виду, что, если я хочу использовать программу в Windows? Возможно, используя многопоточность, я мог проверить p.poll() и запустить только функцию времени, когда она закончилась? – lucacerone

Смежные вопросы