如何在避免MemoryError的同时在大型文件系统中查找重复文件

时间:2015-05-05 22:08:29

标签: python hash duplicates out-of-memory

我试图避免我的mp3集合中的重复(非常大)。我想通过检查文件内容来检查重复项,而不是查找相同的文件名。我已经编写了下面的代码来执行此操作,但它在大约一分钟后抛出了一个MemoryError。关于如何让它发挥作用的任何建议?

import os
import hashlib

walk = os.walk('H:\MUSIC NEXT GEN')

mySet = set()
dupe  = []

hasher = hashlib.md5()

for dirpath, subdirs, files in walk:
    for f in files:
        fileName =  os.path.join(dirpath, f)
        with open(fileName, 'rb') as mp3:
            buf = mp3.read()
            hasher.update(buf)
            hashKey = hasher.hexdigest()
            print hashKey
            if hashKey in mySet:
                dupe.append(fileName)
            else:
                mySet.add(hashKey)


print 'Dupes: ' + str(dupe)

2 个答案:

答案 0 :(得分:3)

您可能有一个巨大的文件,无法像您尝试mp3.read()一样阅读。改为阅读较小的部分。将它放入一个漂亮的小功能也有助于保持主程序的清洁。这是一个我现在已经使用了一段时间的功能(现在只是略微抛光),这个功能可能类似于你的工具:

import hashlib

def filehash(filename):
    with open(filename, mode='rb') as file:
        hasher = hashlib.md5()
        while True:
            buffer = file.read(1 << 20)
            if not buffer:
                return hasher.hexdigest()
            hasher.update(buffer)

更新readinto版本:

buffer = bytearray(1 << 20)
def filehash(filename):
    with open(filename, mode='rb') as file:
        hasher = hashlib.md5()
        while True:
            n = file.readinto(buffer)
            if not n:
                return hasher.hexdigest()
            hasher.update(buffer if n == len(buffer) else buffer[:n])

1GB文件已经缓存在内存中并且有10次尝试,平均花费5.35秒。 read版本平均花费6.07秒。在这两个版本中,Python进程在运行期间占用了大约10MB的RAM。

我可能会坚持使用read版本,因为我更喜欢它的简单性,因为在我的实际使用情况下,数据还没有缓存在RAM中我使用sha256(所以整体时间显着上升,使readinto的小优势更加无关紧要。)

答案 1 :(得分:1)

hasher.update将内容附加到上一个。您可能想为每个文件

创建一个新的hasher