2015-11-25 140 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