【问题标题】:Python execution and sleep timing variancePython 执行和睡眠时间差异
【发布时间】:2014-06-16 18:22:13
【问题描述】:

我正在运行一个脚本来收集数据,我注意到时间上有一些奇怪的变化。

我有一个脚本,它通过 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()。

【问题讨论】:

  • 如果你使用process.join()而不是while循环会发生什么?
  • 另外,请注意您的结束时间和完成时间使用start_time,其中包括创建线程的时间。我猜如果您在创建线程后设置start_time,时间可能会变得更加稳定。你什么时候打电话给process.start()
  • 没有尝试过process.join(),在生产中启动了几个进程,我只是注意到这个有很多不同的结束时间。 (其他的可能也一样,但它们只是输出累积结果,而不是每秒几个)。

标签: python timing variations


【解决方案1】:

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

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

由于 GIL,您正在使用 Python 中不能同时运行的线程。最后,当你运行这些测试时,运行这些测试的计算机在做什么?也许 python 进程没有按应有的频率安排。我之前的评论有点错误,因为时间间隔表明线程创建时间相当恒定。如果您没有显示所有涉及的代码,则可能还有其他因素(例如文件读取/写入导致 IO 等待)。

也许可以尝试一下快速的健全性检查:

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

编辑

从我的评论中再次提出join,如果您使用join,那么主线程将在等待线程时被阻塞并且不会运行任何实际代码。这样就可以给线程任何处理时间来捕获停止信号。

【讨论】:

  • 感谢您的回答!我认为在轮询循环中添加 time.sleep(0.001) 确实有助于缩短时间。我必须做一些测试,看看它是否会改变当时收集的数据点的数量。
猜你喜欢
  • 2022-11-01
  • 2010-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-27
  • 1970-01-01
  • 2012-07-24
相关资源
最近更新 更多