2016-03-18 54 views
5

我創建了以下函數以將數據從文件中提取出來。它工作正常,但對於較大的文件變得非常慢。從文件中獲取數據而無需迭代多次

def get_data(file, indexes, data_start, sieve_first = is_float): 
    file_list = list(file) 
    for i in indexes: 
     d_line = i+data_start 
     for line in file_list[d_line:]: 
      if sieve_first(line.strip().split(',')[0]): 
       yield file_list[d_line].strip() 
       d_line += 1 
      else: 
       break 

def is_float(f): 
    try: 
     float(str(f)) 
    except: 
     return False 
    else: 
     return True 

with open('my_data') as f: 
    data = get_data(f, index_list, 3) 

的文件可能是這樣的(添加爲了清楚行號):

line 1234567: # <-- INDEX 
line 1234568: # +1 
line 1234569: # +2 
line 1234570:  8, 17.0, 23, 6487.6 
line 1234571:  8, 17.0, 23, 6487.6 
line 1234572:  8, 17.0, 23, 6487.6 
line 1234572: 
line 1234572: 
line 1234572: 

隨着上述例子中,線1234570通過1234572將被產生。

由於我的文件很大,有一些我不喜歡我的功能的東西。

  1. 首先是它將整個文件讀入內存;我這樣做,所以我可以使用行索引來解析數據。
  2. 其次,文件中的相同行會迭代多次 - 對於大文件而言,這會非常昂貴。

我已經弄清楚試圖使用迭代器來通過文件一次,但一直未能破解它。有什麼建議麼?

+0

只是'爲文件行而不是'列表(文件)' –

+0

@ cricket_007謝謝,但如果'文件'不支持索引,該函數的其餘部分將無法正常工作。 –

+0

如果該文件不支持索引,那麼你怎麼做'file [d_line:]'? –

回答

2

如果你只想要一小部分文件,我會用itertools.islice。該功能不會存儲任何數據,而是存儲您想要的數據。

下面是一個例子:

from itertools import islice 

def yield_specific_lines_from_file(filename, start, stop): 
    with open(filename, 'rb') as ifile: 
     yield from islice(ifile, start, stop) 

lines = list(yield_specific_lines_from_file('test.txt', 10, 20)) 

這將不緩存,您對線:

from itertools import islice 

def yield_specific_lines_from_file(filename, start, stop): 
    with open(filename, 'rb') as ifile: 
     for line in islice(ifile, start, stop): 
      yield line 

lines = list(yield_specific_lines_from_file('test.txt', 10, 20)) 

如果您使用Python 3.3或更新版本,您還可以通過使用yield from語句簡化此已經從文件中讀取。如果您想這樣做,我建議您將所有讀取的行以行號作爲關鍵字存儲在字典中,並根據需要僅從文件中提取數據。

+1

看起來像'islice'是我所需要的。仍然需要多次迭代,但這種方式的成本要低得多。謝謝。 –

1

在左邊的字段有點。但是,如果你有控制你的文件,你可以將數據移動到sqlite3數據庫。

另請參閱mmap和linecache。我想這些最後兩個只是隨機訪問文件的包裝。即您可以通過掃描文件一次,然後構建索引 - >偏移量查找表並使用查找來自行推出。

其中一些方法假定您對正在閱讀的文件有一些控制權?

還取決於你是否閱讀了很多並且很少寫(如果是這樣,構建索引並不是一個壞主意)。

+0

閱讀很多東西,寫作幾乎從不,但可能偶爾。偉大的想法 - 謝謝! –

相關問題