hashlib zu berechnen mit MD5 in Python einer Datei verdaut 3
-
27-10-2019 - |
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?
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()