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