Есть способ, которым довольно памяти неэффективно .
один файл:
import hashlib
def file_as_bytes(file):
with file:
return file.read()
print hashlib.md5(file_as_bytes(open(full_path, 'rb'))).hexdigest()
список файлов:
[(fname, hashlib.md5(file_as_bytes(open(fname, 'rb'))).digest()) for fname in fnamelst]
Напомним, однако, что MD5 известен как неисправный и не должен использоваться для каких-либо целей, так как анализ уязвимостей может быть очень сложным, а анализ любого возможного будущего использования вашего кода может быть применен для решения проблем безопасности, невозможен , ИМХО, он должен быть полностью удален из библиотеки, чтобы все, кто его использует, были вынуждены обновляться. Итак, вот что вы должны сделать вместо этого:
[(fname, hashlib.sha256(file_as_bytes(open(fname, 'rb'))).digest()) for fname in fnamelst]
Если вам нужен только 128-разрядный дайджест, вы можете сделать .digest()[:16]
.
Это даст вам список кортежей, каждый из которых содержит имя своего файла и его хеш.
Опять я сильно сомневаюсь, что вы используете MD5. Вы должны по крайней мере использовать SHA1, и учитывая недавние недостатки, обнаруженные в SHA1 , вероятно, даже не это. Некоторые люди думают, что пока вы не используете MD5 для «криптографических» целей, все в порядке. Но вещи в конечном итоге оказываются шире, чем вы изначально ожидали, и ваш случайный анализ уязвимостей может оказаться совершенно ошибочным. Лучше всего просто привыкнуть использовать правильный алгоритм из ворот. Это просто набор другой связки букв и все. Это не так сложно.
Вот способ более сложный, но эффективный для памяти :
import hashlib
def hash_bytestr_iter(bytesiter, hasher, ashexstr=False):
for block in bytesiter:
hasher.update(block)
return hasher.hexdigest() if ashexstr else hasher.digest()
def file_as_blockiter(afile, blocksize=65536):
with afile:
block = afile.read(blocksize)
while len(block) > 0:
yield block
block = afile.read(blocksize)
[(fname, hash_bytestr_iter(file_as_blockiter(open(fname, 'rb')), hashlib.md5()))
for fname in fnamelst]
И, опять же, поскольку MD5 сломан и больше не должен использоваться:
[(fname, hash_bytestr_iter(file_as_blockiter(open(fname, 'rb')), hashlib.sha256()))
for fname in fnamelst]
Опять же, вы можете поставить [:16]
после вызова hash_bytestr_iter(...)
, если вы хотите получить только 128-битный дайджест.