2013-06-11 227 views
0

我有一個應用程序每隔幾秒更新一次的文件,並且我想在該文件中提取單個數字段,並將其記錄到列表中供以後使用。所以,我想在腳本讀取源文件的地方進行無限循環,並且每當它發現某個特定圖形發生變化時,就會將該圖形寫入輸出文件。Python:重新讀取文件的內容

我不知道爲什麼我不能讓Python注意到源文件被改變:

#!/usr/bin/python 

import re 
from time import gmtime, strftime, sleep 



def write_data(new_datapoint): 
     output_path = '/media/USBHDD/PythonStudy/torrent_data_collection/data_one.csv' 
     outfile = open(output_path, 'a') 
     outfile.write(new_datapoint) 
     outfile.close() 


forever = 0 
previous_data = "0" 

while forever < 1: 
     input_path = '/var/lib/transmission-daemon/info/stats.json' 
     infile = open(input_path, "r") 
     infile.seek(0) 
     contents = infile.read() 

     uploaded_bytes = re.search('"uploaded-bytes":\s(\d+)', contents) 

     if uploaded_bytes: 
       current_time = strftime("%Y-%m-%d %X", gmtime()) 
       current_data = uploaded_bytes.group(1) 
       if current_data != previous_data: 
         write_data(","+ current_time + "$" + uploaded_bytes.group(1)) 
         previous_data = uploaded_bytes.group(1) 
       infile.close() 
       sleep(5) 
     else: 
       print "couldn't write" + strftime("%Y-%m-%d %X", gmtime()) 
       infile.close() 
       sleep(60) 

由於現在的(凌亂)腳本一次正確寫,然後我可以看到雖然我的源文件(stats.json)文件正在改變,但我的腳本從不改變任何改變。它繼續運行,但我的輸出文件不會增長。

我以爲open()close()會做的伎倆,然後嘗試投擲.seek(0)

我缺少什麼文件方法來確保python重新打開並重新讀取我的源文件(stats.json)?

+0

「其他應用程序」超出了您的控制範圍嗎?有沒有機會修改它的代碼? –

+0

是的,它超出了我的控制範圍。 – polpetti

回答

0

感謝所有的答案,不幸的是我的錯誤是在外殼,而不是與Python腳本。

原因問題原來是我把腳本放在後臺的方式。我在做:Ctrl+Z,我認爲這會把任務放在後臺。但它不,Ctrl+Z只會暫停任務並將您返回到shell,後面的bg命令對於腳本在後臺的無限循環中運行是必要的

2

除非你正在實現一些同步機制,或者可以保證以某種方式進行原子讀寫,否則我認爲你在這裏調用競態條件和微妙的錯誤。

想象一下,「讀取器」訪問文件,而「寫入器」尚未完成其寫週期。有讀取不完整/不一致數據的風險。在「現代」系統中,您也可以點擊緩存 - 並且在附加文件時不會看到「現場」文件修改。

+0

但是這個腳本怎麼才第一次起作用呢?我正在閱讀文件的次數多於其他應用程序正在更改的文件。 – polpetti

1

我能想到的兩種可能的解決方案:

  1. 你忘了在括號中無限循環的其他密切。
    infile.close - >infile.close()
  2. 正在更改JSON文件的程序沒有關閉該文件,因此實際上並未進行更改。
+0

1.修正了括號,這是一個錯誤2.在我的shell中,我可以'cat'文件的內容,並且每隔幾秒就會看到它發生更改 – polpetti

1

兩個問題我看到:

  1. 你確定你的文件確實是更新文件系統?我不知道你在用你的代碼玩什麼操作系統,但是在這種情況下,如果文件沒有被生產者刷新,緩存可能會踢你的$$。
  2. 你的問題是值得考慮的而不是文件,但我不能保證什麼transmission會做,如果它停留在如果你的消費者死寫入管道。

回答你的問題,可以考慮使用以下之一:

這些模塊是爲了監控文件系統的變化,然後調用適當的行動。在你的例子中的方法是原始的,具有很大的性能損失,並且在其他答案中已經提到了其他問題。

+0

性能不是問題,運行在Raspberry pi上,'htop '說這個任務使用0.0%的CPU和1%的內存。這個腳本也是我想在機器上運行的少數幾件事情之一。我會檢查這些解決方法,謝謝。 – polpetti

1

伊利亞,這將有助於檢查(os.path.getmtime),stats.json是否改變了你處理文件之前?

此外,我建議,使的它的JSON文件的事實優勢:

import json 
import os 
import sys 

dir_name ='/home/klaus/.config/transmission/' 
# stats.json of daemon might be elsewhere 

file_name ='stats.json' 
full_path = os.path.join(dir_name, file_name) 

with open(full_path) as fp: 
    json.load(fp) 
    data = json.load(fp) 
    print data['uploaded-bytes'] 
+0

是的,謝謝。 JSON提示非常有幫助。 – polpetti