2017-08-01 58 views
0

我有一個大的文件(1.6演出)與分隔的列表:啜食/ CSV /環路中的文件創建數百萬有列行的字典

[||] 

我曾嘗試使用csv模塊但它說我只能用一個字符作爲分隔符。所以這裏是我有:

fileHandle = open('test.txt', 'r', encoding="UTF-16") 

thelist = [] 

for line in fileHandle: 
    fields = line.split('[||]') 

    therow = { 
     'dea_reg_nbr':fields[0], 
     'bus_actvty_cd':fields[1], 
     'drug_schd':fields[3], 
     #50 more columns like this 
    } 
    thelist.append(therow) 

fileHandle.close() 

#now I have thelist which is what I want 

和繁榮,現在我有一個字典的名單,它的作品。我想要一個清單,因爲我關心訂單,而字典是因爲它是預期的下游。這只是感覺像我應該利用更有效的東西。我認爲這不會超過一百萬行和這麼多的數據。所以,我的問題如下:

以多字符分隔文本文件(UTF-16編碼)和創建字典列表的更有效方式是什麼?

任何想法,將不勝感激!

+2

就這麼你知道,字典是在python 3.6中訂購的;) – Y0da

+2

一個明顯的改進是使用'generator'和'yield'行而不是使用'list',但這不是一個可行的改進,如果你真的需要輸出作爲'list'。 –

+3

這可能是開始與大熊貓合作的好日子。 – Igor

回答

1

使其更好擴展的一種方法是使用生成器,而不是一次將所有百萬行加載到內存中。根據您的使用情況,這可能會也可能不會;如果你只需要對整個數據集進行一次傳遞,它將會工作得最好。多次傳遞將要求您將所有數據以某種形式存儲在內存中,或者多次從文件中讀取。

總之,這裏的你如何使用發電機這個問題的例子:

def file_records(): 
    with open('test.txt', 'r', encoding='UTF-16') as fileHandle: 
     for line in fileHandle: 
      fields = line.split('[||]') 
      therow = { 
       'dea_reg_nbr':fields[0], 
       'bus_actvty_cd':fields[1], 
       'drug_schd':fields[3], 
       #50 more columns like this 
      } 
      yield therow 

for record in file_records(): 
    # do work on one record 

功能file_records是因爲yield關鍵字的生成功能。當這個函數被調用時,它會返回一個迭代器,你可以像列表一樣迭代。 record將按順序返回,並且每個都將是一個字典。

如果你不熟悉發電機,this是開始閱讀它們的好地方。

使這種規模如此出色的事情是你一次只能在內存中擁有一個therow。基本上發生的是,在循環的每次迭代開始時,file_records函數正在讀取文件的下一行並返回計算出的記錄。在進行工作之前,它會一直等到下一行爲止,並且除非需要,否則以前的記錄不會在內存中徘徊(例如,如果它在您在# do work on one record中構建的任何數據結構中引用)。

另請注意,我將open調用移至with聲明。這將確保文件被關閉,並且一旦完成迭代或引發異常,所有相關資源將被釋放。這比試圖自己去捕捉所有這些情況並致電fileHandle.close()簡單得多。

+0

聽起來不錯。我非常感謝這! – sniperd