0

我有一个包含数百万行的大文件(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 编码)并创建字典列表的更有效方法是什么?

任何想法将不胜感激!

4

1 回答 1

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

由于关键字,该函数file_records是生成器函数。yield调用此函数时,它会返回一个迭代器,您可以像列表一样对其进行迭代。records 会按顺序返回,每个都是字典。

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

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

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

于 2017-08-01T15:40:24.977 回答