我有一个备份硬盘,我知道它有散布的重复文件,我认为编写一个小的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)
我仍然得到内存崩溃。
答案 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“文件”