2015-07-11 42 views
0

我有一個程序每秒都會寫入一個文件。文件寫入發生在與UI平行的線程中。由於某些硬件問題,它有時會停止寫一天。我想檢查文件是否停止寫入,如果沒有更新,請重新啓動程序。我想檢查文件的時間戳,看看它是否是不會得到更新(和不想去看門狗等怎麼我只是需要某個文件停筆。)監控文件是否停止在python中寫入

try: 
    if time.time()>(os.stat(filename).st_mtime+2): 
     raise ValueError("Yikes! Spike") 
except ValueError: 
    with open('errors.log','a') as log: 
     log.write('Spike occured at '+ time.strftime(
     "%H:%M:%S")+' on '+datetime.date.today().strftime('%d/%m/%Y')+'\n') 
     log.close() 
    restart_program() 

此塊運行的每一秒。但是,這種情況並沒有發生,當應用程序關閉以重新啓動時,它會每秒關閉並且不會再次啓動。我每秒都會收到異常消息。我試圖增加時差,但沒有幫助。

接着我試圖

ftimestamp = os.stat(filename).st_mtime 
try: 
    if os.stat(filename).st_mtime>=ftimestamp: 
     ftimestamp = time.time() 
     print "ftimestamp updated and all is well" 
    else: 
     ftimestamp = os.stat(filename).st_mtime 
     raise ValueError("Yikes! Spike!") 
     print "file time is behind" 
except ValueError: 
    with open('errors.log','a') as log: 
     log.write('Spike occured at '+ time.strftime(
     "%H:%M:%S")+' on '+datetime.date.today().strftime('%d/%m/%Y')+'\n') 
     log.close() 
    restart_program() 

我試圖更新變量「ftimestamp」到當前時間「了time.time()」,因爲下一個比較只發生之後的一個第二和我想要的文件時要高比以前的時間比較。 (該塊通過wx.CallLater函數每秒運行一次)。

我的程序仍然失敗...我無法理解我要去哪裏錯...有人請幫忙!或者有沒有簡單的檢查文件是否停止寫入的方法?

+0

EOFerror!你有沒有試過 – therealprashant

+0

寫作過程是否每秒刷新它的輸出? – meuh

+0

檢查過程是否仍然存在可能會更簡單。你可以爲此做一個'kill(pid,0)'信號0。 – meuh

回答

2

我們可以嘗試做的文件大小檢查變化是一個可能的解決方案如下:

import os 
from time import sleep 
# other imports 

while True: 
    file1 = os.stat('file.txt') # initial file size 
    file1_size = file1.st_size 

    # your script here that collects and writes data (increase file size) 
    sleep(1) 
    file2 = os.stat('file.txt') # updated file size 
    file2_size = file2.st_size 
    comp = file2_size - file1_size # compares sizes 
    if comp == 0: 
     restart_program() 
    else: 
     sleep(5) 

您可能需要調整sleep()功能因此,這些只是估計,我使用的,因爲我可以不要測試你的實際代碼。最後,這是一個無限循環,只要你希望腳本繼續寫就可以繼續運行。

另一種解決方案是更新您的文件:

import os 
import sys 
from time import sleep 
# other imports 

while True: 
    file1 = os.stat('file.txt') # initial file size 
    file1_size = file1.st_size 

    # your script here that collects and writes data (increase file size) 
    sleep(1) 
    file2 = os.stat('file.txt') # updated file size 
    file2_size = file2.st_size 
    comp = file2_size - file1_size # compares sizes 
    if comp == 0: 
     sys.exit 
    else: 
     sleep(5) 

然後使用輔助程序來運行你的腳本,例如:

import os 
from time import sleep, strftime 

while True: 
    print(strftime("%H:%M:%S), "Starting")) 
    system('main.py') # this is another infinite loop that will keep your script running 
    print(strftime("%H:%M:%S), "Crashed")) 
    sleep(5) 
+0

我沒有奢望在我的腳本中使用睡眠,因爲我的UI將嚴重滯後(使用wx.CallLater函數來設置一些文本字段更新!)。最後的解決方案似乎很有趣在無限循環腳本中運行無限循環腳本有多安全?系統上的密集程度如何?讓我測試一下,然後回到你身邊。感謝你的努力。 –

+0

那麼..你放它的方式*在無限循環內的無限循環*是非常危險的,但是**它們在這種情況下是可控的。只要main.py運行正常(這就是我們想要的),「第二程序」處於無限循環中,對於第二個文件,它在無限循環中直到文件大小不變,因此它們都被控制。作爲主循環的輔助程序,如果終止,也將終止所有其他的程序。 – Leb

+0

第一個解決方案對我來說不起作用,因爲UI掛起,第二個解決方案不起作用bcoz文件在線程中得到更新,而不是按照您的假設順序更新。試過其他使用文件大小的方式也是徒勞的。我嘗試的最後一個,但問題是它重新啓動應用程序,但仍然無限期地重新啓動。看起來時間戳例外無限期地發生並繼續崩潰。但再次感謝您的努力。 –

1

要確定是否在時間的文件更改一個GUI程序,你可以使用你的事件循環的標準工具,運行一個函數每間隔秒,例如,這裏是如何做到這一點tkinter

#!/usr/bin/env python3 
import logging 
import os 
import sys 
import tkinter 
from datetime import datetime 
from time import monotonic as timer, localtime 

path = sys.argv[1] 
interval = 120 # check every 2 minutes 

def check(last=[None]): 
    mtime = os.path.getmtime(path) # or os.path.getsize(path) 
    logging.debug("mtime %s", datetime.fromtimestamp(mtime)) 
    if last[0] == mtime: #NOTE: it is always False on the first run 
     logging.error("file metadata hasn't been updated, exiting..") 
     root.destroy() # exit GUI 
    else: # schedule the next run 
     last[0] = mtime 
     root.after(round(1000 * (interval - timer() % interval)), check) 


logging.basicConfig(level=logging.DEBUG, 
        filename=os.path.splitext(__file__)[0] + ".log", 
        format="%(asctime)-15s %(message)s", datefmt="%F %T") 
root = tkinter.Tk() 
root.withdraw() # hide GUI 
root.after(round(1000 * (interval - timer() % interval)), check) # start on boundary 
root.mainloop() 

你可以使用supervisord或systemd或upstart等自動重生你的腳本。

請參閱How to run a function periodically in python

+0

謝謝你的代碼。我在wxpython中使用類似的函數來調用wx.CallLater(1,some_function())中的root.after()。由於我的應用程序全都是用wx編寫的,現在不能回去了!感謝您的努力... –

+0

@RohinKumar:'tkinter'只是一個例子。 「使用標準工具」表明你應該在你的GUI框架('wx')中使用更合適的東西。如果它是'wx.CallLater()',那麼使用'wx.CallLater()' - 程序結構(算法)不會改變。如果你不想(不能)使用[看門狗或它的模擬器與推送接口](http://pythonhosted.org/watchdog/quickstart.html#a-simple-example),那麼對定時器進行輪詢就是一個合理的選擇。 – jfs

+0

是您的算法也可以與CallLater一起使用。我的程序遇到了更多問題。稍微修改一下,我想我已經開始工作了。 –

1

最後,在對基於時間戳的選項進行修改之後,以下內容似乎適用於我。

try: 
    if time.time()-os.stat(filename).st_mtime>6: 
     touch(filename) 
     raise ValueError("Yikes! Spike") 
except ValueError: 
    with open('errors.log','a') as log: 
     log.write('Spike/App restarting occured at '+ time.strftime(
       "%H:%M:%S")+' on '+datetime.date.today().strftime('%d/%m/%Y')+'\n') 
     log.close() 
    restart_program() 

此前,問題是它會檢測到文件停止寫入給定的時間間隔,並繼續滿足相同的。

time.time()-os.stat(filename).st_mtime>6 

但是,一旦這個條件成立,除非該文件的時間戳更新它繼續滿足這一條件,並會不斷重啓程序。現在在我的解決方案中,我「觸及」了文件一次(touch used from here)條件滿足,現在它按預期工作。

謝謝大家的意見。

+0

嘗試重新啓動腳本時,即使在執行「觸摸」操作後,它仍然停留在同一個循環中。無法重新啓動! –

+0

似乎腳本重新啓動的方式有問題。請參閱http://stackoverflow.com/questions/31447442/difference-between-os-execl-and-os-execv-in-python –