2012-10-01 67 views
3

我有一個包含數字列表(每行1個數字)的22mb文本文件。我試圖讓python讀取數字,處理數字並將結果寫入另一個文件。所有這些工作,但如果我必須停止該計劃,它從頭開始從頭開始。起初我嘗試使用mysql數據庫,但速度太慢。我以這種方式處理的數字是約4倍。我希望能夠在處理號碼後刪除該行。您可以在每次重新啓動時看到它必須搜索硬盤驅動器的文件名以確保它到達停止的位置。有了150萬的數字,這可能需要一段時間。我發現一個截斷的例子,但它沒有工作。從文件中讀取行,處理它,然後將其刪除

是否有任何類似於array_shift(PHP)的python命令可用於文本文件。

+0

數字是否是唯一的? – kalgasnik

+0

您是否正在嘗試將每個數字寫入單獨的文件?如果是這樣,爲什 – root

+0

你可以嘗試使用Postgres和pl/pgsql來執行數據庫本身的任何計算...... – moooeeeep

回答

7

我會用一個標記文件,以保持處理,而不是重寫輸入文件中的最後一行的數:

start_from = 0 

try: 
    with open('last_line.txt', 'r') as llf: start_from = int(llf.read()) 
except: 
    pass 

with open('list.txt', 'r') as file: 
    for i, line in enumerate(file): 
     if i < start_from: continue 

     filename = line.rstrip('\n') + ".txt" 
     if os.path.isfile(filename): 
      print "File", filename, "exists, skipping!" 
     else: 
      pass 
     with open('last_line.txt', 'w') as outfile: outfile.write(str(i)) 

此代碼首先檢查該文件last_line.txt並嘗試從讀出的數它。該數字是上次嘗試期間處理的行數。然後,它只需跳過所需的行數。

+1

+1,很好的答案 - 你可以利用[enumerate](http://docs.python.org/library/functions.html#enumerate)刪除'i + = 1'部分。 – girasquid

+0

值得檢查一下用例是什麼在中間停止的地方。在每一行上寫文件最終會成爲你花費大部分時間的地方。如果沒有中途停止的情況,最好是明確地說明這些情況,而不是做數千次不必要的文件寫入。如果你的程序只是隨機死亡,那麼每100或1000行寫一次也許會更好。 – BostonJohn

+1

也許我錯過了一些東西,但是這個解決方案不會跳過第一行嗎?在第一次通過循環時,我們迭代i以使它大於0 - 所以實際上讀取的第一行是第一行,而不是第0行不是它? – sager89

1

我使用Redis來做類似的東西。安裝redis,然後安裝pyredis,並且可以在內存中擁有一個持久集。然後,你可以這樣做:

r = redis.StrictRedis('localhost') 
with open('list.txt', 'r') as file: 
    for line in file: 
     if r.sismember('done', line): 
      continue 
     else: 
      #process number and write file 
      r.sadd('done', line) 

,如果你不想安裝的Redis您還可以使用擱置模塊,確保你與所述寫回= False選項打開它。儘管我真的推薦Redis,但它讓這樣的事情變得更加容易。

1

讀取數據文件不應該是瓶頸。下面的代碼在大約0.2秒讀36 MB,697997行文本文件我的機器上:

import time 

start = time.clock() 
with open('procmail.log', 'r') as f: 
    lines = f.readlines() 
end = time.clock() 
print 'Readlines time:', end-start 

因爲它產生以下結果:

Readlines time: 0.1953125 

注意,此代碼生成一個列表線條一氣呵成。

要知道你去過的地方,只需將你處理的行數寫入文件。然後如果您想再試一次,請閱讀所有行並跳過您已完成的行:

import os 

# Raad the data file 
with open('list.txt', 'r') as f: 
    lines = f.readlines() 

skip = 0 
try: 
    # Did we try earlier? if so, skip what has already been processed 
    with open('lineno.txt', 'r') as lf: 
     skip = int(lf.read()) # this should only be one number. 
     del lines[:skip] # Remove already processed lines from the list. 
except: 
    pass 

with open('lineno.txt', 'w+') as lf: 
    for n, line in enumerate(lines): 
     # Do your processing here. 
     lf.seek(0) # go to beginning of lf 
     lf.write(str(n+skip)+'\n') # write the line number 
     lf.flush() 
     os.fsync() # flush and fsync make sure the lf file is written. 
相關問題