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().

简单得多