slurp/csv/循环文件以创建字典列表

2024-09-22 16:30:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个大文件(1.6 Gig),其中有数百万行,其中的列以:

[||]

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

任何想法都将不胜感激!你知道吗


Tags: 模块文件csvfields列表字典lineopen
1条回答
网友
1楼 · 发布于 2024-09-22 16:30:20

使其更好地扩展的一种方法是使用生成器,而不是一次将所有百万行加载到内存中。这可能是可能的,也可能是不可能的,这取决于您的用例;如果您只需要对整个数据集进行一次传递,那么它将工作得最好。多次传递将要求您以某种形式或另一种形式将所有数据存储在内存中,或者多次从文件中读取数据。你知道吗

总之,下面是一个如何使用生成器解决此问题的示例:

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

函数file_records是一个生成器函数,因为yield关键字。调用此函数时,它将返回一个迭代器,您可以像列表一样对其进行迭代。record将按顺序返回,每一个都将是一个字典。你知道吗

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

使这个比例如此之好的原因是你一次只能在内存中有一个therow。实际上,在循环的每次迭代开始时,file_records函数读取文件的下一行并返回计算的记录。它将一直等到下一行需要时才执行该工作,并且上一条记录不会在内存中保留,除非需要(例如,它是否在您在# do work on one record中构建的任何数据结构中引用)。你知道吗

还要注意,我将open调用移到了with语句。这将确保在迭代完成或引发异常后关闭文件并释放所有相关资源。这比自己尝试捕捉所有这些案例并调用fileHandle.close()要简单得多。你知道吗

相关问题 更多 >