2012-08-02 162 views
1

我在Stack Overflow中發現了一些類似的問題,但我相信我可以從特定於我的案例的建議中受益。從文件中讀取數字列表的最快方法

我必須在一個文件中存儲大約8萬個實值數字列表,並在稍後讀取它們。

首先,我想cPickle,但閱讀時間沒有吸引力:

>>> stmt = """ 
with open('pickled-data.dat') as f: 
    data = cPickle.load(f) 
""" 
>>> timeit.timeit(stmt, 'import cPickle', number=1) 
3.8195440769195557 

後來我發現,存儲數字作爲明文允許更快的讀取(有道理的,因爲cPickle必須擔心很多東西):

>>> stmt = """ 
data = [] 
with open('text-data.dat') as f: 
    for line in f: 
     data.append([float(x) for x in line.split()]) 
""" 
>>> timeit.timeit(stmt, number=1) 
1.712096929550171 

這是一個很好的改善,但我認爲我仍然可以優化它在某種程度上,因爲其他語言編寫的程序可以從文件中顯着更快的讀取類似的數據。

任何想法?

+1

如果你存儲這麼多的列表,sqlite數據庫是不是一個更好的數據結構? – BrtH 2012-08-02 14:28:13

+0

您是否嘗試過'csv'模塊的閱讀器?它會避免你所調用的手動分割。 – jmetz 2012-08-02 14:28:56

+1

@BrtH數據庫看起來像是一種矯枉過正,我只需要加載所有這些列表。 – erickrf 2012-08-02 15:46:39

回答

2

如果numpy的陣列是可行的,numpy.fromfile將可能是讀取文件(這裏有一個somewhat related question我問只是一對夫婦日前)

或者,好像你的表現會更好一點與struct最快的選項,儘管我還沒有測試過它:

import struct 
def write_data(f,data): 
    f.write(struct.pack('i',len())) 
    for lst in data: 
     f.write(struct.pack('i%df'%len(lst),len(lst),*lst)) 

def read_data(f): 
    def read_record(f): 
     nelem = struct.unpack('i',f.read(4))[0] 
     return list(struct.unpack('%df'%nelem,f.read(nelem*4))) #if tuples are Ok, remove the `list`. 

    nrec = struct.unpack('i',f.read(4))[0] 
    return [ read_record(f) for i in range(nrec) ] 

這假定將數據存儲爲4字節的浮點數就足夠了。如果您想要一個真正的雙精度數字,請將格式語句從f更改爲d並將nelem*4更改爲nelem*8。這裏可能存在一些次要的可移植性問題(例如,數據類型的字節順序和sizeof)。

+0

我懷疑numpy fromfile是相對優化的,可能是比結構,情況允許更好的解決方案。 – jmetz 2012-08-02 14:38:01

+0

@mutzmatron - 是的,可能 - 雖然真的不應該有太大的差異。我敢打賭,他們幾乎完成同樣的事情 - numpy的優點是它可以將對象放入順序存儲器中(本質上只需要分配1塊和1個指針來操作指針)。另一方面struct可能仍然只分配一個塊,但它也需要一個讀取每個浮點的指針,所以這是一個額外的工作。無論哪種方式,我希望它比讀取ASCII文本更快,將其轉換爲浮動(全部在非類型化的python框架內完成)。 – mgilson 2012-08-02 14:41:14

+0

謝謝,'numpy.fromfile'耗時0.02秒。 – erickrf 2012-08-02 16:04:06

相關問題