处理文件时内存错误Python

时间:2015-09-07 16:16:14

标签: python python-2.7

我有一个备份硬盘,我知道它有散布的重复文件,我认为编写一个小的python脚本来找到它们并删除它们将是一个有趣的项目。我编写了下面的代码只是为了遍历驱动器并计算每个文件的md5总和,并将其与我将要称之为“#34;第一次遇到"名单。如果md5总和尚不存在,则将其添加到列表中。如果总和已存在,请删除当前文件。

import sys
import os
import hashlib

def checkFile(fileHashMap, file):
    fReader = open(file)
    fileData = fReader.read();
    fReader.close()
    fileHash = hashlib.md5(fileData).hexdigest()
    del fileData

    if fileHash in fileHashMap:
        ### Duplicate file.
        fileHashMap[fileHash].append(file)
        return True
    else:
        fileHashMap[fileHash] = [file]
        return False


def main(argv):
    fileHashMap = {}
    fileCount = 0
    for curDir, subDirs, files in os.walk(argv[1]):
        print(curDir)
        for file in files:
            fileCount += 1
            print("------------: " + str(fileCount))
            print(curDir + file)
            checkFile(fileHashMap, curDir + file)

if __name__ == "__main__":
    main(sys.argv)

该脚本处理大约10Gb的文件,然后在行' fileData = fReader.read()'上抛出MemoryError。我认为,因为我在关闭fReader并在计算md5总和之后将fileData标记为删除,所以我不会遇到这种情况。如何计算md5总和而不会遇到此内存错误?

编辑:我被要求删除字典并查看内存使用情况,以查看hashlib中是否存在泄漏。这是我跑的代码。

import sys
import os
import hashlib

def checkFile(file):
    fReader = open(file)
    fileData = fReader.read();
    fReader.close()
    fileHash = hashlib.md5(fileData).hexdigest()
    del fileData

def main(argv):
    for curDir, subDirs, files in os.walk(argv[1]):
        print(curDir)
        for file in files:
            print("------: " + str(curDir + file))
            checkFile(curDir + file)

if __name__ == "__main__":
    main(sys.argv)

我仍然得到内存崩溃。

3 个答案:

答案 0 :(得分:4)

您的问题在于读取整个文件,它们太大而您的系统无法将其全部加载到内存中,因此会引发错误。

正如您在官方Python文档中所看到的,MemoryError是:

  

当操作内存不足时引发,但情况可能如此   仍然被救出(通过删除一些对象)。相关值是a   指示哪种(内部)操作耗尽内存的字符串。   请注意,由于底层的内存管理架构   (C的malloc()函数),解释器可能并不总是能够   完全从这种情况中恢复;然而,它提出了一个   异常,以便可以打印堆栈回溯,以防丢失   程序是原因。

出于您的目的,您可以使用hashlib.md5()

在这种情况下,您必须按顺序读取4096字节的块并将它们提供给Md5函数:

def md5(fname):
    hash = hashlib.md5()
    with open(fname) as f:
        for chunk in iter(lambda: f.read(4096), ""):
            hash.update(chunk)
    return hash.hexdigest()

答案 1 :(得分:1)

不是您的内存问题的解决方案,而是可以避免它的优化:

  • 小文件:计算md5总和,删除重复项

  • 大文件:记住大小和路径

  • 最后,只有当有多个文件时才计算相同大小的文件的md5sums

Python collection.defaultdict可能对此有用。

答案 2 :(得分:0)

如何从python调用openssl命令 在Windows和Linux中

$ openssl md5“文件”