【问题标题】:slurp/csv/loop a file to create a list of dictionariesslurp/csv/loop 一个文件来创建一个字典列表
【发布时间】:2018-01-08 13:01:01
【问题描述】:

我有一个包含数百万行的大文件(1.6 gigs),其中的列分隔为:

[||]

我尝试使用 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 编码)并创建字典列表的更有效方法是什么?

任何想法将不胜感激!

【问题讨论】:

  • 请注意,字典是在 python 3.6 中排序的;)
  • 一个明显的改进是使用generatoryield 行而不是使用list,但是如果您确实需要将输出作为list,这不是一个可行的改进.
  • 这可能是开始使用 pandas 的好日子。
  • 谈到内存使用,namedtuple 或带有__slots__ 的简单类将通过避免为每一行创建一个dict 来节省一些字节。见this answer
  • @TomWyllie:当人们真正需要的是一个可迭代对象时,通常会创建一个列表......如果 OP 稍后一次处理一个字典,那么生成器将非常好并且具有高度可扩展性

标签: python list csv dictionary slurp


【解决方案1】:

让它更好地扩展的一种方法是使用生成器,而不是一次将所有数百万行加载到内存中。根据您的用例,这可能会也可能不会;如果您只需要对整个数据集进行一次传递,它将效果最佳。多次传递将要求您以某种形式将所有数据存储在内存中,或者从文件中多次读取。

不管怎样,这里有一个例子说明如何使用生成器来解决这个问题:

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 是一个生成器函数。调用此函数时,它会返回一个迭代器,您可以像列表一样对其进行迭代。 records 会按顺序返回,每个都是字典。

如果您不熟悉生成器,this 是开始阅读它们的好地方。

使这个规模如此出色的原因是您一次只能在内存中拥有一个therow。基本上发生的事情是,在循环的每次迭代开始时,file_records 函数正在读取文件的下一行并返回计算记录。它会等到需要下一行才开始工作,除非需要,否则前一条记录不会留在内存中(例如,如果它在您在 # do work on one record 中构建的任何数据结构中引用)。

还请注意,我将 open 调用移至 with 语句。这将确保一旦迭代完成或引发异常,文件就会关闭并释放所有相关资源。这比尝试自己捕获所有这些情况并致电fileHandle.close() 要简单得多。

【讨论】:

    猜你喜欢
    • 2017-05-01
    • 2018-09-18
    • 1970-01-01
    • 2015-09-16
    • 2023-04-08
    • 2019-11-29
    • 1970-01-01
    • 2020-02-06
    • 2021-11-25
    相关资源
    最近更新 更多