我需要在Python中获取文件的哈希(摘要)。
通常,在处理任何文件内容时,建议由于内存问题逐行逐行处理,但我需要加载整个文件才能获取其摘要。
目前我正以这种方式获取哈希:
import hashlib
def get_hash(f_path, mode='md5'):
h = hashlib.new(mode)
with open(f_path, 'rb') as file:
data = file.read()
h.update(data)
digest = h.hexdigest()
return digest
还有其他方法可以更优化或更清洁的方式执行此操作吗?
在读取整个文件的同时逐行读取文件是否有任何显着改善还是必须加载整个文件来计算哈希?
答案 0 :(得分:3)
当然,您可以以块的形式加载数据,这样内存使用量就会大幅下降,因为您不再需要加载整个文件。然后对每个块使用hash.update(chunk)
:
from functools import partial
Hash = hashlib.new("sha1")
size = 128 # just an example
with open("data.txt", "rb") as File:
for chunk in iter(partial(f.read, size), b''):
Hash.update(chunk)
我发现这个iter
技巧非常简洁,因为它允许编写更清晰的代码。起初可能看起来很混乱,所以我将解释它是如何工作的:
iter(function, sentinel)
连续执行function
并生成它返回的值,直到其中一个等于sentinel
。 partial(f.read, size)
返回f.read(size)
的可调用版本。这是过于简单的,但在这种情况下仍然是正确的。 答案 1 :(得分:1)
两个片段都会得到相同的结果:
h = hashlib.new("md5")
with open(filename,"rb") as f:
for line in f:
h.update(line)
print(h.hexdigest())
和
h = hashlib.new("md5")
with open(filename,"rb") as f:
h.update(f.read())
print(h.hexdigest())
一些注意事项:
答案 2 :(得分:1)
根据hashlib.update()的文档,您不必关心不同散列算法的块大小。但是,我测试了一下。但是,似乎要检查,512是MD5的块大小,如果你将其改为其他任何东西,结果与一次读取它的结果相同。
import hashlib
def get_hash(f_path, mode='md5'):
h = hashlib.new(mode)
with open(f_path, 'rb') as file:
data = file.read()
h.update(data)
digest = h.hexdigest()
return digest
def get_hash_memory_optimized(f_path, mode='md5'):
h = hashlib.new(mode)
with open(f_path, 'rb') as file:
block = file.read(512)
while block:
h.update(block)
block = file.read(512)
return h.hexdigest()
digest = get_hash('large_bin_file')
print(digest)
digest = get_hash_memory_optimized('large_bin_file')
print(digest)
> bcf32baa9b05ca3573bf568964f34164
> bcf32baa9b05ca3573bf568964f34164