136

我希望 python 读取 EOF,以便我可以获得适当的哈希,无论是 sha1 还是 md5。请帮忙。这是我到目前为止所拥有的:

import hashlib

inputFile = raw_input("Enter the name of the file:")
openedFile = open(inputFile)
readFile = openedFile.read()

md5Hash = hashlib.md5(readFile)
md5Hashed = md5Hash.hexdigest()

sha1Hash = hashlib.sha1(readFile)
sha1Hashed = sha1Hash.hexdigest()

print "File Name: %s" % inputFile
print "MD5: %r" % md5Hashed
print "SHA1: %r" % sha1Hashed
4

7 回答 7

192

TL;DR 使用缓冲区来不使用大量内存。

我相信,当我们考虑处理非常大的文件对内存的影响时,我们就找到了问题的症结所在。我们不希望这个坏小子通过 2 GB 的内存来处理 2 GB 的文件,因此,正如pasztorpisti指出的那样,我们必须分块处理这些更大的文件!

import sys
import hashlib

# BUF_SIZE is totally arbitrary, change for your app!
BUF_SIZE = 65536  # lets read stuff in 64kb chunks!

md5 = hashlib.md5()
sha1 = hashlib.sha1()

with open(sys.argv[1], 'rb') as f:
    while True:
        data = f.read(BUF_SIZE)
        if not data:
            break
        md5.update(data)
        sha1.update(data)

print("MD5: {0}".format(md5.hexdigest()))
print("SHA1: {0}".format(sha1.hexdigest()))

我们所做的是在使用 hashlib 方便的花花公子更新方法时,我们以 64kb 的块更新了这个坏男孩的哈希值。这样一来,我们使用的内存比一次对这个家伙进行哈希处理所需的 2gb 少得多!

您可以使用以下方法进行测试:

$ mkfile 2g bigfile
$ python hashes.py bigfile
MD5: a981130cf2b7e09f4686dc273cf7187e
SHA1: 91d50642dd930e9542c39d36f0516d45f4e1af0d
$ md5 bigfile
MD5 (bigfile) = a981130cf2b7e09f4686dc273cf7187e
$ shasum bigfile
91d50642dd930e9542c39d36f0516d45f4e1af0d  bigfile

希望有帮助!

所有这些都在右侧的链接问题中进行了概述:Get MD5 hash of big files in Python


附录!

一般来说,在编写 python 时,它有助于养成遵循pep-8的习惯。例如,在 python 中,变量通常用下划线分隔,而不是驼峰式。但这只是风格,没有人真正关心这些事情,除了那些不得不阅读糟糕风格的人......这可能是你从现在开始阅读这段代码。

于 2014-02-27T03:52:35.533 回答
97

为了正确有效地计算文件的哈希值(在 Python 3 中):

  • 以二进制模式打开文件(即添加'b'到文件模式)以避免字符编码和行尾转换问题。
  • 不要将完整的文件读入内存,因为那是对内存的浪费。相反,按块顺序读取它并更新每个块的哈希值。
  • 消除双缓冲,即不要使用缓冲 IO,因为我们已经使用了最佳块大小。
  • 用于readinto()避免缓冲区搅动。

例子:

import hashlib

def sha256sum(filename):
    h  = hashlib.sha256()
    b  = bytearray(128*1024)
    mv = memoryview(b)
    with open(filename, 'rb', buffering=0) as f:
        for n in iter(lambda : f.readinto(mv), 0):
            h.update(mv[:n])
    return h.hexdigest()
于 2017-07-02T17:23:47.387 回答
32

我会简单地提议:

def get_digest(file_path):
    h = hashlib.sha256()

    with open(file_path, 'rb') as file:
        while True:
            # Reading is buffered, so we can read smaller chunks.
            chunk = file.read(h.block_size)
            if not chunk:
                break
            h.update(chunk)

    return h.hexdigest()

这里的所有其他答案似乎都太复杂了。Python 在读取时已经在缓冲(以理想的方式,或者如果您有更多关于底层存储的信息,则可以配置该缓冲),因此最好以块的形式读取散列函数认为理想的块,这样可以更快或至少减少 CPU 密集度计算哈希函数。因此,与其禁用缓冲并尝试自己模拟它,不如使用 Python 缓冲并控制您应该控制的内容:数据的使用者找到理想的散列块大小。

于 2019-04-05T19:56:01.463 回答
10

这是一个 Python 3、POSIX 解决方案(不是 Windows!),用于mmap将对象映射到内存中。

import hashlib
import mmap

def sha256sum(filename):
    h  = hashlib.sha256()
    with open(filename, 'rb') as f:
        with mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ) as mm:
            h.update(mm)
    return h.hexdigest()
于 2020-06-05T11:54:39.500 回答
7

我编写了一个模块,它能够使用不同的算法对大文件进行哈希处理。

pip3 install py_essentials

像这样使用模块:

from py_essentials import hashing as hs
hash = hs.fileChecksum("path/to/the/file.txt", "sha256")
于 2018-02-12T00:57:14.200 回答
1

FWIW,我更喜欢这个版本,它具有与 maxschlepzig 的答案相同的内存和性能特征,但 IMO 更具可读性:

import hashlib

def sha256sum(filename, bufsize=128 * 1024):
    h = hashlib.sha256()
    buffer = bytearray(bufsize)
    # using a memoryview so that we can slice the buffer without copying it
    buffer_view = memoryview(buffer)
    with open(filename, 'rb', buffering=0) as f:
        while True:
            n = f.readinto(buffer_view)
            if not n:
                break
            h.update(buffer_view[:n])
    return h.hexdigest()
于 2021-12-03T13:27:57.947 回答
-2
import hashlib
user = input("Enter ")
h = hashlib.md5(user.encode())
h2 = h.hexdigest()
with open("encrypted.txt","w") as e:
    print(h2,file=e)


with open("encrypted.txt","r") as e:
    p = e.readline().strip()
    print(p)
于 2018-06-10T09:04:12.887 回答