باستخدام hashlib لحساب MD5 هضم من ملف في بيثون 3
-
27-10-2019 - |
سؤال
ومع الثعبان 2.7 التعليمة البرمجية التالية يحسب hexdigest MD5 من محتويات الملف.
و(تحرير: حسنا، ليست حقا كما أظهرت الإجابات، أنا مجرد التفكير بذلك)
.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) الباحث). ويفسر هذا السلوك في مكان ما؟
المحلول
وأعتقد أنك أراد حلقة لإجراء المكالمات المتتالية إلى f.read(128)
. التي يمكن أن يتم ذلك باستخدام ايتر () م> و <م> 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()