2014-06-16 84 views
0

我正在运行一个脚本来收集数据,并且我注意到了时间的一些奇怪的变化。Python执行和睡眠时间差异

我有一个通过FTDI库查询I2C数据的脚本,它以3.5HZ的速率提取数据。它坚实而且效果很棒。这是(我们称之为poll_data.py):加入

while time.time() < start_time + duration_in_seconds: 
    if not stop_queue.empty(): 
     if stop_queue.get(): 
      logger.debug('Break received, exiting collection after {0} seconds'.format(time.time() - start_time)) 
      break 
    data = get_data() 
    cache.append(",".join(str(x) for x in [time.time() - start_time] + data])) 
    counter += 1 
    if len(cache) == 50: 
     write_to_log_file(file_id, cache) 
     cache = [] 

队列因此该脚本可以异步运行,并通过一些外部的计时停止。

运行一些测试后,我注意到我得到了奇怪的停止时间。说我有一个简单的测试:

import time 
from threading import Thread 
from poll_data import polling, stop_queue 

start_time = time.time() 
test_time = 60 
duration = 80 
process = Thread(target=polling, args=duration) 
process.start() 
interval = test_time - (time.time() - start_time) 
time.sleep(interval) 
stop = time.time() 
stop_queue.put(True) 
while process.is_alive(): 
    pass 
end = time.time() 
run_information.append((start_time, interval, stop - start_time, end - start_time)) 

运行这个105倍(实际上它在运行x次,这里缩短为了便于阅读的循环)后,我看到在执行时间一些奇怪的变化。下面是一个小样本

      Run information        
    Start  | Interval  | Process End | Finished  
1402934605.5525 |   59.9994 |   61.5621 |   64.3632 
1402934670.9171 |   59.9991 |   60.5022 |   62.8066 
1402934734.7252 |   59.9995 |   71.3656 |   77.0946 
1402934812.8211 |   59.9996 |   61.4797 |   61.6411 
1402934875.4637 |   59.9995 |   60.7879 |   60.7954 
1402934937.2605 |   59.9995 |   60.2218 |   60.5099 
1402934998.7719 |   59.9995 |   62.2200 |   65.0900 
1402935064.8633 |   59.9994 |   60.0802 |   60.4974 
1402935126.3622 |   59.9994 |   61.5364 |   63.3869 
1402935190.7505 |   59.9995 |   61.5147 |   61.9220 



Average Interval 59.99951714 Max 59.9998  Min 59.9991 
       62.28667048  71.3757   60.0485 
       64.23963714  77.0946   60.2074 

我很好奇,为什么睡眠间隔似乎总是相同的,但停止时间是非常不同的,而结束时间为也。该项目放入队列后立即结束该过程,但似乎需要一段时间?

这是怎么回事?

编辑:添加process.start()在适当的地方。

+0

如果使用'process.join()'而不是while循环,会怎样? – daveydave400

+0

另外,请注意您的结束时间和完成时间使用'start_time',其中包括创建线程的时间。我猜测如果在创建线程后设置'start_time',时间可能会变得更加稳定。你什么时候调用'process.start()'? – daveydave400

+0

还没有尝试过process.join(),在生产过程中开始了几个过程,我只注意到这个过程有很多不同的结束时间。 (其他人可能也会这样做,但他们只是输出累计结果,而不是每秒几个)。 – polkid

回答

1

这可能不是一个令人满意的答案,但我认为这只是基于操作系统调度,因为您所显示的代码看起来不会造成任何其他延迟。这里有几个重要的因素。您正在使用sleep函数本身说,它可能需要更少或更多的时间取决于:

https://docs.python.org/2/library/time.html#time.sleep

您正在使用的在Python是不是因为GIL的并发运行的线程。最后,当你运行这些测试时,计算机运行的是什么?也许python进程没有像应该那样经常进行计划。我之前的评论有点不对,因为间隔显示线程创建时间非常稳定。如果没有显示所有代码,可能还有其他因素(例如导致IO等待的文件读取/写入)。

也许尝试一个快速的健全性检查:

import time 
start = time.time() 
time.sleep(60) 
stop = time.time() 
print stop - start 

编辑

,并从我的评论重提join,如果使用join然后主线程将被阻止在等待线程并且不会运行任何实际的代码。这样任何处理时间都可以提供给线程来捕捉停止信号。

+0

感谢您的回答!我认为在轮询循环中增加一个time.sleep(0.001)确实有助于缩短计时的原因。我将不得不做一些测试,看看它是否会改变那时收集的数据点的数量。 – polkid