【问题标题】:Creating list of dictionaries from big csv从大 csv 创建字典列表
【发布时间】:2016-02-28 10:18:40
【问题描述】:

我有一个非常大的 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)

问题是基本上它会因为列表变得太大而耗尽内存并且进程被杀死。 有没有办法以有效的方式实现相同的结果(字典列表)?我对生成器/产量非常陌生,所以我什至不知道我是否正确使用它。

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

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

【问题讨论】:

  • 如果存储生成器的完整结果,则不会节省内存。如果目标是逐行处理文件,则逐行处理,不要存储。另外,旁注:yield {key: value for key, value in row.items()} 只是浅拷贝dict,当你已经有一个非常好的dict,直接做yield row

标签: python csv dictionary generator avro


【解决方案1】:

如果目标是从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 一次写入一行。输入行在写入后被丢弃,因此内存使用量保持最小。

如果您需要修改行,您需要在csv_reader 生成器中修改row,然后再进行yield-ing。

【讨论】:

  • 谢谢,它有效。现在我只需要了解如何在 fastavro 中使用不同的编解码器:D
猜你喜欢
  • 2015-09-16
  • 2014-11-11
  • 2022-01-14
  • 2021-02-19
  • 2016-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-20
相关资源
最近更新 更多