为什么Python计算的"hashlib.sha1"与"git hash-object"对一个文件结果不同?
我正在尝试计算一个文件的SHA-1值。
我写了这个脚本:
def hashfile(filepath):
sha1 = hashlib.sha1()
f = open(filepath, 'rb')
try:
sha1.update(f.read())
finally:
f.close()
return sha1.hexdigest()
对于一个特定的文件,我得到了这个哈希值:
8c3e109ff260f7b11087974ef7bcdbdc69a0a3b9
但是当我用git的hash_object命令计算这个值时,我得到了这个值:d339346ca154f6ed9e92205c3c5c38112e761eb7
为什么这两个值会不同呢?我是不是做错了什么,还是说我可以忽略这个差异?
2 个回答
32
作为参考,这里有一个更简洁的版本:
def sha1OfFile(filepath):
import hashlib
with open(filepath, 'rb') as f:
return hashlib.sha1(f.read()).hexdigest()
再想想:虽然我从来没有见过,但我觉得 f.read()
可能会返回不完整的文件内容,或者在处理一个好几GB的文件时,f.read()
可能会导致内存不足。为了大家的理解,我们来看看怎么解决这个问题:第一个解决办法是:
def sha1OfFile(filepath):
import hashlib
sha = hashlib.sha1()
with open(filepath, 'rb') as f:
for line in f:
sha.update(line)
return sha.hexdigest()
不过,文件里不一定会有 '\n'
,所以 for
循环给我们的文件块如果以 '\n'
结尾,可能会让我们遇到最初的问题。可惜的是,我没有找到类似 Python 风格的方法来尽可能大块地遍历文件,这意味着我们可能得用 while True: ... break
循环,并且需要一个神秘的数字来表示块的大小:
def sha1OfFile(filepath):
import hashlib
sha = hashlib.sha1()
with open(filepath, 'rb') as f:
while True:
block = f.read(2**10) # Magic number: one-megabyte blocks.
if not block: break
sha.update(block)
return sha.hexdigest()
当然,谁能说我们能存储一兆字节的字符串呢?我们可能可以,但如果我们在一个小型嵌入式计算机上呢?
我希望能想到一种更简洁的方法,确保在处理超大文件时不会耗尽内存,而且没有神秘数字,同时性能也能和原来的简单 Python 解决方案一样好。
52