25

Python 2.7では、次のコードはファイルのコンテンツのmD5hexdigestを計算します。

(編集:まあ、答えが示しているように実際にはそうではありません、私はちょうどそう思った)。

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()

今でも、なぜ元のコードが機能しなくなったのか疑問に思います。バイナリモード修飾子を使用してファイルを開くと、バイトとしてエンコードされた文字列ではなく整数が返されるようです(type(buf)はintを返すためです)。この動作はどこかで説明されていますか?

4

3 に答える 3

37

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'))
于 2011-10-19T23:59:49.970 に答える
10
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()
于 2011-10-19T23:42:45.883 に答える
1

質問をした後、ようやくコードを以下のバージョン(わかりやすいバージョン)に変更しました。しかし、私はおそらくそれをRaymondHettingが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()
于 2011-10-20T00:20:32.553 に答える