2010-01-04 62 views
4

我正在使用python的csv模塊從外部工具不斷更新的csv中提取數據。我遇到了一個問題,當我到達文件末尾時,出現StopIteration錯誤,但是,我希望腳本繼續循環等待外部工具添加更多行。在更新文件時使用Python csv模塊

我想出了迄今爲止要做到這一點:

f = open('file.csv') 
csvReader = csv.reader(f, delimiter=',') 
while 1: 
    try: 
     doStuff(csvReader.next()) 
    except StopIteration: 
     depth = f.tell() 
     f.close() 
     f = open('file.csv') 
     f.seek(depth) 
     csvReader = csv.reader(f, delimiter=',') 

這有預期的功能,但它似乎也太可怕了。在捕獲StopIteration之後循環是不可能的,因爲一旦拋出StopIteration,它將在每次後續調用next()時拋出StopIteration。任何人對如何實施這個建議都有這樣的想法,我不需要做這個愚蠢的告訴和尋求?或者有一個不同的python模塊可以很容易地支持這個功能。

回答

4

您的問題不在於CSV閱讀器,而在於文件對象本身。您可能仍然需要在上面的代碼片段中做一些瘋狂的迴轉動作,但是最好創建一個文件對象包裝器或子類,並將其用於您的CSV閱讀器。這可以使複雜性與您的csv處理代碼隔離開來。

例如(警告:未經測試的代碼):

class ReopeningFile(object): 
    def __init__(self, filename): 
     self.filename = filename 
     self.f = open(self.filename) 

    def next(self): 
     try: 
      self.f.next() 
     except StopIteration: 
      depth = self.f.tell() 
      self.f.close() 
      self.f = open(self.filename) 
      self.f.seek(depth) 
      # May need to sleep here to allow more data to come in 
      # Also may need a way to signal a real StopIteration 
      self.next() 

    def __iter__(self): 
     return self 

然後你的主代碼變得更簡單,因爲它不必管理文件重新打開釋放(注意,您也不必重新啓動csv_reader只要文件重新啓動:

import csv 
csv_reader = csv.reader(ReopeningFile('data.csv')) 
for each in csv_reader: 
    process_csv_line(each) 
0

你很少需要明確地趕上StopIteration。這樣做:

for row in csvReader: 
    doStuff(row) 

至於何時新行寫入文件檢測,您可以要麼popen方法一tail -f過程或寫出什麼tail -f做的Python代碼。 (這並不複雜,它基本上只是stat s文件每一秒,看它是否已經改變Here's the C source code of tail.。)

編輯:令人失望的是,popening tail -f如我所料在Python 2.x中不起作用看起來,使用fread和大量緩衝區來實現對文件行的迭代,即使該文件應該是無緩衝的(例如,當subprocess.py創建文件,傳遞bufsize = 0時)。反正tail無論如何都會是一個溫和的醜陋黑客。

2

生產者 - 消費者的東西可能會有點棘手。如何使用查找和讀取字節呢?使用命名管道怎麼樣?

哎呀,爲什麼不通過本地套接字進行通信?

+0

+1:命名管道。放棄文件。使用更簡單併爲此目的而構建的東西。 – 2010-01-05 00:21:36