slurp/csv/loop 用于创建字典列表的文件
slurp/csv/loop a file to create a list of dictionaries
我有一个包含数百万行的大文件(1.6 GB),其中的列分隔为:
[||]
我尝试使用 csv 模块,但它说我只能使用单个字符作为分隔符。所以这就是我所拥有的:
fileHandle = open('test.txt', 'r', encoding="UTF-16")
thelist = []
for line in fileHandle:
fields = line.split('[||]')
therow = {
'dea_reg_nbr':fields[0],
'bus_actvty_cd':fields[1],
'drug_schd':fields[3],
#50 more columns like this
}
thelist.append(therow)
fileHandle.close()
#now I have thelist which is what I want
太棒了,现在我有了一个字典列表,而且可以用了。我想要一个列表是因为我关心顺序,而字典是因为它在下游是被期望的。这只是 感觉 就像我应该利用更有效的东西一样。我认为这不能很好地扩展超过一百万行和这么多数据。所以,我的问题如下:
获取多字符分隔文本文件(UTF-16 编码)并创建字典列表的更有效方法是什么?
如有任何想法,我们将不胜感激!
使其扩展性更好的一种方法是使用生成器,而不是一次将所有百万行加载到内存中。根据您的用例,这可能会也可能不会;如果您只需要遍历整个数据集,效果会最好。多次传递将要求您以某种形式将所有数据存储在内存中,或者多次从文件中读取它。
无论如何,这是一个如何使用生成器解决此问题的示例:
def file_records():
with open('test.txt', 'r', encoding='UTF-16') as fileHandle:
for line in fileHandle:
fields = line.split('[||]')
therow = {
'dea_reg_nbr':fields[0],
'bus_actvty_cd':fields[1],
'drug_schd':fields[3],
#50 more columns like this
}
yield therow
for record in file_records():
# do work on one record
由于 yield
关键字,函数 file_records
是一个生成器函数。当这个函数被调用时,它 returns 一个迭代器,你可以像列表一样迭代它。 record
会按顺序返回,每一个都是一个字典。
如果您不熟悉生成器,this 是开始阅读它们的好地方。
使此秤如此出色的原因是您一次只能在内存中存储一个 therow
。本质上发生的事情是在循环的每次迭代开始时,file_records
函数正在读取文件的下一行并返回计算的记录。它会等到需要下一行才开始工作,除非需要(例如如果它在您在 # do work on one record
中构建的任何数据结构中被引用),否则之前的记录不会留在内存中。
另请注意,我将 open
调用移到了 with
语句中。这将确保在迭代完成或引发异常后关闭文件并释放所有相关资源。这比自己尝试捕获所有这些情况并调用 fileHandle.close()
.
简单得多
我有一个包含数百万行的大文件(1.6 GB),其中的列分隔为:
[||]
我尝试使用 csv 模块,但它说我只能使用单个字符作为分隔符。所以这就是我所拥有的:
fileHandle = open('test.txt', 'r', encoding="UTF-16")
thelist = []
for line in fileHandle:
fields = line.split('[||]')
therow = {
'dea_reg_nbr':fields[0],
'bus_actvty_cd':fields[1],
'drug_schd':fields[3],
#50 more columns like this
}
thelist.append(therow)
fileHandle.close()
#now I have thelist which is what I want
太棒了,现在我有了一个字典列表,而且可以用了。我想要一个列表是因为我关心顺序,而字典是因为它在下游是被期望的。这只是 感觉 就像我应该利用更有效的东西一样。我认为这不能很好地扩展超过一百万行和这么多数据。所以,我的问题如下:
获取多字符分隔文本文件(UTF-16 编码)并创建字典列表的更有效方法是什么?
如有任何想法,我们将不胜感激!
使其扩展性更好的一种方法是使用生成器,而不是一次将所有百万行加载到内存中。根据您的用例,这可能会也可能不会;如果您只需要遍历整个数据集,效果会最好。多次传递将要求您以某种形式将所有数据存储在内存中,或者多次从文件中读取它。
无论如何,这是一个如何使用生成器解决此问题的示例:
def file_records():
with open('test.txt', 'r', encoding='UTF-16') as fileHandle:
for line in fileHandle:
fields = line.split('[||]')
therow = {
'dea_reg_nbr':fields[0],
'bus_actvty_cd':fields[1],
'drug_schd':fields[3],
#50 more columns like this
}
yield therow
for record in file_records():
# do work on one record
由于 yield
关键字,函数 file_records
是一个生成器函数。当这个函数被调用时,它 returns 一个迭代器,你可以像列表一样迭代它。 record
会按顺序返回,每一个都是一个字典。
如果您不熟悉生成器,this 是开始阅读它们的好地方。
使此秤如此出色的原因是您一次只能在内存中存储一个 therow
。本质上发生的事情是在循环的每次迭代开始时,file_records
函数正在读取文件的下一行并返回计算的记录。它会等到需要下一行才开始工作,除非需要(例如如果它在您在 # do work on one record
中构建的任何数据结构中被引用),否则之前的记录不会留在内存中。
另请注意,我将 open
调用移到了 with
语句中。这将确保在迭代完成或引发异常后关闭文件并释放所有相关资源。这比自己尝试捕获所有这些情况并调用 fileHandle.close()
.