从大 csv 创建字典列表

Creating list of dictionaries from big csv

我有一个非常大的 csv 文件 (10 gb),我想阅读它并创建一个词典列表,其中每个词典代表 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)

问题是基本上它会因为列表变得太大而耗尽内存并且进程被终止。 有没有办法以有效的方式实现相同的结果(字典列表)?我是 generators/yield 的新手,所以我什至不知道我是否正确使用它。

我也尝试过使用 pypy 的虚拟环境,但无论如何内存都会中断(不过稍后)。

基本上,我想要一个字典列表的原因是我想尝试使用 fastavro 将 csv 转换为 avro 格式,因此关于如何使用 fastavro (https://pypi.python.org/pypi/fastavro) 的任何提示都无需创建列表字典将不胜感激

如果目标是从 csv 转换为 avro,则没有理由存储输入值的完整列表。这违背了使用生成器的全部目的。看起来,在设置架构后,fastavro's writer is designed to take an iterable and write it out one record at a time,因此您可以直接将其传递给生成器。例如,您的代码将简单地省略创建 list 的步骤(旁注:命名变量 list 是一个坏主意,因为它 shadows/stomps 内置名称 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 一次写入一行。输入行在写入后被丢弃,因此内存使用量保持最小。

如果您需要修改行,您需要在 yield-ing 之前修改 csv_reader 生成器中的 row