Frage

Mit Python 2.7 der folgende Code berechnet die mD5 hexdigest des Inhalts einer Datei.

(EDIT: na ja, nicht wirklich als Antworten gezeigt haben, dachte ich nur so)

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

Nun, wenn ich diesen Code verwenden python3 führen Sie es eine Typeerror-Ausnahme erhöhen:

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

Ich fand heraus, dass ich diesen Code laufen sowohl mit python2 und python3 Wechsel machen könnte es an:

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

Jetzt frage ich mich immer noch, warum der ursprüngliche Code funktioniert nicht mehr. Es scheint, dass, wenn eine Datei mit dem Binär-Modus zu öffnen Modifikator es ganze Zahlen anstelle von Strings zurückgibt als Bytes codiert (ich sage das, weil Typ (buf) zurückgibt int). Ist dieses Verhalten erklärt irgendwo?

War es hilfreich?

Lösung

Ich glaube, Sie die for-Schleife wollte aufeinanderfolgende Aufrufe f.read(128) zu machen. Das kann mit Hilfe getan werden iter () und 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'))

Andere Tipps

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

.. aktualisiert den Hash nacheinander mit jedem der ersten 128 Bytes Werten der Datei. Da Iterieren über eine bytes int Objekte erzeugt, erhalten Sie die folgenden Anrufe, die den Fehler verursachen Sie in Python3 angetroffen werden.

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

das ist nicht das, was Sie wollen.

Stattdessen Sie wollen:

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

ich meinen Code endlich geändert auf die Version unten (die ich leicht zu verstehen finden), nachdem die Frage zu stellen. Aber ich werde es wohl auf die von Raymond Hetting unsing functools.partial vorgeschlagene Version ändern.

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()
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top