Python读取一个巨大的文件并消除重复的行

时间:2015-04-26 16:57:39

标签: python large-files

我有一个巨大的文本文件,有重复的行。大小约为150000000行。我想找到最有效的方法来阅读这些行并消除重复。我考虑的一些方法如下: -

  1. 读入整个文件,列表(设置(行))。
  2. 一次读取10k行,在我拥有的列表上设置(设置(行)),在列表中读取另外10k行,做一个列表(设置(行))。重复。
  3. 你会如何解决这个问题?任何形式的多处理都有帮助吗?

3 个答案:

答案 0 :(得分:7)

多处理实际上没有用,因为你的瓶颈就是内存。你需要使用哈希:

  1. 读取行
  2. 计算哈希,例如md5,在​​一组遇到的所有哈希中查找它。
  3. 如果在集合中找不到散列,则输出行,并将此散列添加到set。
  4. 要注意的事情:

    • md5需要128位,所以即使没有开销,也不会超过2G的ram。
    • set和dict有很大的内存开销。

    所以,如果你有4个以上的演出,这是可行的。更具可扩展性的解决方案是将遇到的哈希存储在磁盘上的已排序文件中,并且每次都搜索它们。这将(很多!)慢,但你可以拥有你想要的低内存占用。

    此外,如果您不关心结果文件中的行排序,您可以根据一些散列函数将文件拆分为较小的文件(md5以a开头的行,md5以b开头的行等)。这将允许你使它们足够小到仅sort | uniq它们(或者如果你愿意的话,用python在内存中排序)并连接结果。

答案 1 :(得分:5)

此处的内存存在问题,因此无法将整个文件加载到内存中。

由于您不需要维护行的排序,因此有一个潜在的选择是进行某种基数排序:

for each line in file:
    put this line into a new file based on the first character

新文件现在应该要小一些,如果某些文件仍然太大(例如,每一行),您可以根据第二,第三等字符递归拆分文件在原始文件中以a开头。

一旦这些文件足够小以适应内存,您就可以执行list(set(list))方法,然后在完成后将cat文件重新组合在一起。或者,如果您可以使用uniq UNIX命令行工具,则可以使用它。

请注意,基数排序部分可以很容易地并行化,因为每一行都独立于其他行。

答案 2 :(得分:0)

想想你真的是否需要在python本身解决这个问题。你可以

  • 呼叫大多数posix系统上存在的标准工具sortuniq。他们会在你考虑它们之前完成工作,更快并解决边缘情况(例如内存不足)
  • 最简单的解决方案可能是使用sqlite - 包创建内存数据库,将所有行插入临时表并从中执行select distinct...。同样,sqlite在纯python中的表现会比你自己做得更好。