我正在运行一个脚本来收集数据,我注意到时间上有一些奇怪的变化。
我有一个脚本通过FTDI库轮询I2C数据,并以3.5 HZ的速率提取数据。它很坚固,效果很好。这是(我们称之为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 :(得分: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
,则主线程将在等待线程时被阻止,并且不会运行任何实际代码。这样,任何处理时间都可以给线程捕获停止信号。