Подтвердить что ты не робот

Почему Python вычисляет "hashlib.sha1", отличный от "git hash-object" для файла?

Я пытаюсь вычислить значение SHA-1 файла.

Я создал этот script:

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

Как они отличаются? Я что-то делаю неправильно, или могу просто игнорировать разницу?

4b9b3361

Ответ 1

git вычисляет хэши следующим образом:

sha1("blob " + filesize + "\0" + data)

Ссылка

Ответ 2

Для справки, здесь более краткий вариант:

def sha1OfFile(filepath):
    import hashlib
    with open(filepath, 'rb') as f:
        return hashlib.sha1(f.read()).hexdigest()

Во второй раз: хотя я никогда этого не видел, я думаю, что потенциал f.read() для возврата меньше, чем полный файл, или для файла с большим гигабайтом, для 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', может дать нам ту же самую проблему, которую мы изначально, К сожалению, я не вижу аналогичного метода Pythonic для итерации по блокам файла как можно больше, что, я думаю, означает, что мы застряли в цикле 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()

Конечно, кто сказал, что мы можем хранить одно мегабайтные строки. Возможно, мы сможем, но что, если мы на крошечном встроенном компьютере?

Мне жаль, что я не мог подумать о более чистом способе, который, как гарантируется, не исчерпывает память огромными файлами и не имеет магических чисел, а также выполняет первоначальное простое решение Pythonic.