2015-11-25 137 views
1

我有一個非常大的csv文件(10 GB),我想閱讀它並創建一個詞典列表,其中每個詞典表示csv中的一行。 喜歡的東西從大csv創建詞典列表

[{'value1': '20150302', 'value2': '20150225','value3': '5', 'IS_SHOP': '1', 'value4': '0', 'value5': 'GA321D01H-K12'}, 
{'value1': '20150302', 'value2': '20150225', 'value3': '1', 'value4': '0', 'value5': '1', 'value6': 'GA321D01H-K12'}] 

我想,以避免任何的記憶問題,使用發電機來實現它,我當前的代碼如下:

def csv_reader(): 
    with open('export.csv') as f: 
     reader = csv.DictReader(f) 
     for row in reader: 
      yield {key: value for key, value in row.items()} 

generator = csv_reader() 
list = [] 
for i in generator: 
    list.append(i) 

的問題是,基本上用完由於列表變得太大而導致進程中斷,因此內存不足。 有沒有辦法以有效的方式實現相同的結果(字典列表)?我很新的發電機/產量,所以我甚至不知道我是否正確使用它。

我也嘗試使用pypy的虛擬環境,但內存仍然中斷(稍後雖然)。

基本上我爲什麼要,將不勝感激

,我想嘗試使用fastavro等如何使用fastavro( https://pypi.python.org/pypi/fastavro)任何提示到CSV轉換成Avro的格式,而無需創建一個字典列表字典它的列表的原因
+1

如果您存儲了生成器的完整結果,則說明您沒有保存內存。如果目標是逐行處理文件,然後逐行處理,則不要存儲它。另外,注意:當你已經有一個非常好的'dict'時,'yield {key:key的值,row.items()}中的值'只是淺拷貝'dict',直接'yield row' 。 – ShadowRanger

回答

3

如果目標是將csv轉換爲avro,則沒有理由存儲輸入值的完整列表。這破壞了使用發生器的全部目的。它看起來像設置了一個模式fastavro's writer is designed to take an iterable and write it out one record at a time,因此您可以直接將它傳遞給生成器。例如,您的代碼會簡單地忽略創建list的步驟(邊注:命名變量list是一個壞主意,因爲它陰影/重踏內置的名字list),而直接寫入發電機:

from fastavro import writer 

def csv_reader(): 
    with open('export.csv') as f: 
     reader = csv.DictReader(f) 
     for row in reader: 
      yield row 

    # If this is Python 3.3+, you could simplify further to just: 
    with open('export.csv') as f: 
     yield from csv.DictReader(f) 

# schema could be from the keys of the first row which gets manually written 
# or you can provide an explicit schema with documentation for each field 
schema = {...} 

with open('export.avro', 'wb') as out: 
    writer(out, schema, csv_reader()) 

然後發生器一次產生一行,並且writer一次寫入一行。輸入行在寫入後被丟棄,所以內存使用量保持最小。

如果您需要修改行,您可以在生成器中修改row之前的yield

+0

謝謝,它的工作原理。現在我只需要了解如何在fastavro中使用不同的編解碼器:D – user2697881