有没有更快的方法(比这个)在Python中计算文件的哈希值(使用hashlib)?

时间:2014-03-29 16:45:22

标签: python hashlib

我目前的做法是:

def get_hash(path=PATH, hash_type='md5'):
    func = getattr(hashlib, hash_type)()
    with open(path, 'rb') as f:
         for block in iter(lambda: f.read(1024*func.block_size, b''):
             func.update(block)
    return func.hexdigest()

在i5 @ 1.7 GHz上计算842MB iso文件的md5sum大约需要3.5秒。我尝试过不同的读取文件的方法,但所有这些方法都会产生较慢的结果。也许还有更快的解决方案吗?

编辑:我将2**16f.read()内)替换为1024*func.block_size,因为hashlib支持的大多数哈希函数的默认block_size64(除了'sha384'和'sha512' - 对于他们来说,默认block_size128)。因此,块大小仍然相同(65536位)。

编辑(2):我做错了什么。它需要8.4秒而不是3.5秒。 :(

编辑(3):当我再次运行该功能时,显然Windows正在使用+ 80%的磁盘。这真的需要3.5秒。呼。

另一个解决方案(〜-0.5秒,稍快)是使用os.open():

def get_hash(path=PATH, hash_type='md5'):
    func = getattr(hashlib, hash_type)()
    f = os.open(path, (os.O_RDWR | os.O_BINARY))
    for block in iter(lambda: os.read(f, 2048*func.block_size), b''):
        func.update(block)
    os.close(f)
    return func.hexdigest()

请注意,这些结果不是最终结果。

1 个答案:

答案 0 :(得分:1)

使用md5 openssl工具需要2秒的874 MiB随机数据文件,我能够提高速度,如下所示。

  • 使用第一种方法需要21秒。
  • 读取整个文件(21秒)以缓冲,然后更新所需的2秒。
  • 使用缓冲区大小为8096的以下函数需要17秒。
  • 使用缓冲区大小为32767的以下函数需要11秒。
  • 使用以下函数,缓冲区大小为65536,需要8秒。
  • 使用以下函数,缓冲区大小为131072需要8秒。
  • 使用以下函数,缓冲区大小为1048576,需要12秒。

def md5_speedcheck(path, size): pts = time.process_time() ats = time.time() m = hashlib.md5() with open(path, 'rb') as f: b = f.read(size) while len(b) > 0: m.update(b) b = f.read(size) print("{0:.3f} s".format(time.process_time() - pts)) print("{0:.3f} s".format(time.time() - ats))

人类时间就是我上面提到的。而所有这些的处理器时间与IO阻塞的差异大致相同。

这里的关键决定因素是,缓冲区大小足以缓解磁盘延迟,但小到足以避免VM页面交换。对于我的特定机器,似乎64 KiB是最佳的。