2014-06-16 87 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