我使用过hashlib(它取代了Python 2.6/3.0中的md5),如果我打开一个文件并将其内容放在hashlib.md5()函数中,它工作得很好。

问题是对于非常大的文件,它们的大小可能超过RAM大小。

如何在不将整个文件加载到内存的情况下获得文件的MD5哈希值?


当前回答

import hashlib,re
opened = open('/home/parrot/pass.txt','r')
opened = open.readlines()
for i in opened:
    strip1 = i.strip('\n')
    hash_object = hashlib.md5(strip1.encode())
    hash2 = hash_object.hexdigest()
    print hash2

其他回答

Python < 3.7

import hashlib

def checksum(filename, hash_factory=hashlib.md5, chunk_num_blocks=128):
    h = hash_factory()
    with open(filename,'rb') as f: 
        for chunk in iter(lambda: f.read(chunk_num_blocks*h.block_size), b''): 
            h.update(chunk)
    return h.digest()

Python 3.8及以上版本

import hashlib

def checksum(filename, hash_factory=hashlib.md5, chunk_num_blocks=128):
    h = hash_factory()
    with open(filename,'rb') as f: 
        while chunk := f.read(chunk_num_blocks*h.block_size): 
            h.update(chunk)
    return h.digest()

最初的发布

如果你想要一个更Pythonic (no while True)的方式读取文件,检查下面的代码:

import hashlib

def checksum_md5(filename):
    md5 = hashlib.md5()
    with open(filename,'rb') as f: 
        for chunk in iter(lambda: f.read(8192), b''): 
            md5.update(chunk)
    return md5.digest()

请注意,iter()函数需要一个空字节字符串,以便返回的迭代器在EOF处停止,因为read()返回b "(不仅仅是")。

你需要以合适大小的块读取文件:

def md5_for_file(f, block_size=2**20):
    md5 = hashlib.md5()
    while True:
        data = f.read(block_size)
        if not data:
            break
        md5.update(data)
    return md5.digest()

注意:确保你用'rb'打开你的文件-否则你会得到错误的结果。

所以要在一种方法中完成所有的事情-使用如下的方法:

def generate_file_md5(rootdir, filename, blocksize=2**20):
    m = hashlib.md5()
    with open( os.path.join(rootdir, filename) , "rb" ) as f:
        while True:
            buf = f.read(blocksize)
            if not buf:
                break
            m.update( buf )
    return m.hexdigest()

上面的更新是基于Frerich Raabe提供的评论——我测试了一下,发现在我的Python 2.7.2 Windows安装上是正确的

我用jacksum工具反复核对了结果。

jacksum -a md5 <filename>

我认为下面的代码更python化:

from hashlib import md5

def get_md5(fname):
    m = md5()
    with open(fname, 'rb') as fp:
        for chunk in fp:
            m.update(chunk)
    return m.hexdigest()
import hashlib,re
opened = open('/home/parrot/pass.txt','r')
opened = open.readlines()
for i in opened:
    strip1 = i.strip('\n')
    hash_object = hashlib.md5(strip1.encode())
    hash2 = hash_object.hexdigest()
    print hash2

使用多个评论/回答这个问题,以下是我的解决方案:

import hashlib
def md5_for_file(path, block_size=256*128, hr=False):
    '''
    Block size directly depends on the block size of your filesystem
    to avoid performances issues
    Here I have blocks of 4096 octets (Default NTFS)
    '''
    md5 = hashlib.md5()
    with open(path,'rb') as f:
        for chunk in iter(lambda: f.read(block_size), b''):
             md5.update(chunk)
    if hr:
        return md5.hexdigest()
    return md5.digest()

这是python式的 这是一个函数 它避免隐式值:总是偏爱显式值。 它允许(非常重要的)性能优化