2015-07-20 2 views
1

Я написал сценарий для чтения с инструмента и записи данных в CSV-файл. Интервал времени между каждой выборкой может быть задан пользователем. Частота выборки в секунду является довольно распространенной. Я использовал time.sleep и попытался извлечь время обработки для скрипта, используя timeElapsed = timeEnd - timeBegin. Проблема в том, что это недостаточно. Время дрейфует, поэтому время от времени скрипт перескакивает через секунду. На моем компьютере это происходит примерно каждые 2-3 минуты. Поэтому мой вопрос заключается в том, как я могу повысить точность времени.Запуск в цикле каждую секунду

import csv 
import datetime 
import time 
import os.path 

no_of_meas = 200 
cur_meas = 1 
time_interval= 1 #time between each sample given in seconds, 1 second is the lowest recommended value 

with open('test.csv', 'a', newline='') as fp: 
    while cur_meas <= no_of_meas: 
     timeBegin = time.time() 
     cur_time = datetime.datetime.strftime(datetime.datetime.now(), '%H:%M:%S.%f') 
     a = csv.writer(fp, delimiter='\t') 
     data = [[cur_time, cur_meas]] 
     a.writerows(data) 
     fp.flush() #flush and os.fsync to be sure that data is written to disk 
     os.fsync(fp.fileno()) 
     print(', '.join(map(str, data))) 
     cur_meas += 1 
     timeEnd = time.time() 
     timeElapsed = timeEnd - timeBegin 
     time.sleep(time_inter-timeElapsed) 
+3

Вместо того чтобы спать, проверьте, больше или равно текущее время; таким образом, ошибка не может накапливаться. –

+0

Я думаю, что это то, что вы хотите: http://stackoverflow.com/a/13151104/3881403 –

ответ

0

Вы не должны переустанавливать базовое время при каждом вызове, так как вы создаете новую шкалу времени, которая слегка выключена. Вы должны выполнить расчет с глобальной базы времени. И вам нужно использовать float, чтобы убедиться, что Python не выполняет округление целых чисел.

Только соответствующие части:

interval = 1.0 
start_time = time.time() 

with open('test.csv', 'a', newline='') as fp: 
    while cur_meas <= no_of_meas: 
     next_in = (start_time + (cur_meas - 1.0) * interval) - time.time() 
     if next_in > 0.0: 
      time.sleep(next_in) 
     # your measuring code. 

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

+0

Спасибо, что это работает очень хорошо. Я запустил сценарий в течение ночи на двух компьютерах, около 62000 образцов, я не пропустил ни секунды, и он не перепрыгнул через секунды. –

0

Вам нужно заложить задержку на фактическое время, а не за итерационную задержку. Ниже приведен возможный альтернативный способ борьбы с ним, который не будет дрейфовать в течение длительного времени, но будет использовать дробно большее количество CPU.

import time 

def tick(time_interval): 
    next_tick = time.time() + time_interval 
    while True: 
     time.sleep(0.2)  # Minimum delay to allow for catch up 
     while time.time() < next_tick: 
      time.sleep(0.2) 

     yield True 
     next_tick += time_interval 

time_interval = 1.0 
ticker = tick(time_interval) 

while cur_meas <= no_of_meas: 
    # Do measurement code 
    next(ticker) 

Индивидуальные итерации будут до следующих 0,2 с (или, как бы там ни было необходимо). Если итерация задерживается (например, загрузка ЦП), это позволит «догнать» каждые 0.2 секунды, пока время не будет синхронизировано снова.

+0

Это не сработало для меня. Может быть, я что-то замалчивал, но время сильно подпрыгнуло. Когда-то я получал по 2-3 образца каждую секунду, в других случаях он прыгал через два или два раза. –

+0

Можете ли вы скопировать/вставить снова, я немного изменил его после публикации. 2-3 выборки будут возникать только в том случае, если скрипт застыл более секунды, а затем отметит каждые 0.2 секунды, пока не настигнет. –

+0

Теперь он работает лучше. Он отсчитывает каждую секунду, и точность кажется довольно хорошей. –