使用蟒2.7以下代码计算一个文件的内容的MD5 hexdigest。

(编辑:很好,没有真正的答案所显示的,我只是认为如此)

import hashlib

def md5sum(filename):
    f = open(filename, mode='rb')
    d = hashlib.md5()
    for buf in f.read(128):
        d.update(buf)
    return d.hexdigest()

现在,如果我使用python3运行代码它引发TypeError例外:

    d.update(buf)
TypeError: object supporting the buffer API required

我想通了,我可以作出这样的代码的运行与两个python2和python3其更改为:

def md5sum(filename):
    f = open(filename, mode='r')
    d = hashlib.md5()
    for buf in f.read(128):
        d.update(buf.encode())
    return d.hexdigest()

现在我仍然不知道为什么原来的代码停止工作。看来,使用二进制模式修改打开一个文件时,它返回一个整数编码为字节字符串(我这样说是因为类型(BUF)返回INT)。这种行为解释的地方?

有帮助吗?

解决方案

我想你想的for循环做出f.read(128)连续调用。可以使用来进行的 ITER() functools.partial()

import hashlib
from functools import partial

def md5sum(filename):
    with open(filename, mode='rb') as f:
        d = hashlib.md5()
        for buf in iter(partial(f.read, 128), b''):
            d.update(buf)
    return d.hexdigest()

print(md5sum('utils.py'))

其他提示

for buf in f.read(128):
  d.update(buf)

..更新散列依次与每个第一128 字节文件的值。由于迭代一个bytes产生int对象,你会得到以下调用,使你在Python3遇到的错误。

d.update(97)
d.update(98)
d.update(99)
d.update(100)

这是不是你想要的。

相反,你想要的:

def md5sum(filename):
  with open(filename, mode='rb') as f:
    d = hashlib.md5()
    while True:
      buf = f.read(4096) # 128 is smaller than the typical filesystem block
      if not buf:
        break
      d.update(buf)
    return d.hexdigest()

我终于(我发现很容易理解)提出这个问题后,改变了我的代码下面的版本。不过,我可能会改变它由雷蒙德Hetting unsing functools.partial建议的版本。

import hashlib

def chunks(filename, chunksize):
    f = open(filename, mode='rb')
    buf = "Let's go"
    while len(buf):
        buf = f.read(chunksize)
        yield buf

def md5sum(filename):
    d = hashlib.md5()
    for buf in chunks(filename, 128):
        d.update(buf)
    return d.hexdigest()
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top