2017-08-01 56 views
0

我有一个大的文件(1.6演出)与分隔的列表:啜食/ CSV /环路中的文件创建数百万有列行的字典

[||] 

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

任何想法,将不胜感激!

+2

就这么你知道,字典是在python 3.6中订购的;) – Y0da

+2

一个明显的改进是使用'generator'和'yield'行而不是使用'list',但这不是一个可行的改进,如果你真的需要输出作为'list'。 –

+3

这可能是开始与大熊猫合作的好日子。 – Igor

回答

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关键字的生成功能。当这个函数被调用时,它会返回一个迭代器,你可以像列表一样迭代。 record将按顺序返回,并且每个都将是一个字典。

如果你不熟悉发电机,this是开始阅读它们的好地方。

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

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

+0

听起来不错。我非常感谢这! – sniperd