当前位置:首页 > 文章列表 > 文章 > python教程 > Python hashlib.file_digest 怎样直接计算文件摘要

Python hashlib.file_digest 怎样直接计算文件摘要

来源:17golang原创 2026-11-13 18:29:38 0浏览 收藏

如果目标是从一个已经打开的二进制文件直接得到 SHA-256、SHA-512 等摘要,Python 3.11 及以上可以使用 hashlib.file_digest()。它把“读取文件、持续更新哈希对象、返回最终摘要”这段固定样板收拢成一次调用:

import hashlib

def file_sha256(path):
    # 以二进制、阻塞模式打开文件,file_digest 会消费其中的内容。
    with open(path, "rb") as source:
        digest = hashlib.file_digest(source, "sha256")
    # hexdigest 适合写入清单、日志或与另一份十六进制摘要比较。
    return digest.hexdigest()

官方地址:https://docs.python.org/3/library/hashlib.html#hashlib.file_digest

这篇只讨论文件对象、摘要算法、文件位置和迁移边界,不把文件摘要当成密码存储方案,也不展开大文件分片协议。

file_digest 解决的是哪一段重复代码

旧代码通常先创建哈希对象,再循环读取固定大小的字节块,最后调用 hexdigest()。这种写法没有错,但每个项目都要重复处理块大小、循环结束和资源关闭。file_digest(fileobj, digest) 直接接收一个可读的二进制文件对象,并返回已经更新完成的摘要对象。

第二个参数可以是算法名称字符串、哈希构造器,或返回哈希对象的可调用对象。得到的仍然是标准 hashlib 哈希对象,因此可以继续使用 digest()、hexdigest() 和 name 等接口。它不是把结果直接返回成字符串,格式化动作仍由调用方决定。

Python hashlib.file_digest 从二进制文件对象连接到摘要对象和十六进制结果的静态结构图
图1:file_digest 的静态调用关系;文件对象提供字节内容,算法参数决定摘要对象,调用方再选择二进制或十六进制结果。

用算法名称直接计算 SHA-256

最常见的场景是把算法名作为字符串传入。文件必须用 rb 打开,因为摘要计算针对的是原始字节;如果用文本模式读取,换行转换或编码处理就可能让摘要与原文件不一致。

from pathlib import Path
import hashlib

def digest_file(path: str, algorithm: str = "sha256") -> str:
    # 先保留路径语义,打开动作放在 with 内,确保异常时也能关闭句柄。
    file_path = Path(path)
    with file_path.open("rb") as source:
        digest = hashlib.file_digest(source, algorithm)
    # 返回稳定的十六进制文本,不把摘要对象泄漏到资源管理范围之外。
    return digest.hexdigest()

sha256_text = digest_file("release.tar.gz")
print(sha256_text)

算法名称写错或当前构建不可用时,异常会在调用处暴露。不要为了“兼容”而静默改成另一个算法,否则清单和校验端会得到不同语义。发布文件校验一般会约定算法名与十六进制大小写,保存摘要前先确定这两个约定。

文件位置和关闭责任不能忽略

file_digest 会消费文件对象的内容。官方文档还特别提醒:函数可能绕过 Python 层 I/O,直接使用 fileno(),调用成功或抛出异常后,文件对象都应视为处于未知状态。因此最稳妥的边界是为一次摘要创建一个新打开的文件对象,并让 with 负责关闭。

import hashlib

def digest_from_existing(source) -> str:
    # 调用方若复用文件对象,必须先明确自己要摘要的字节范围。
    source.seek(0)
    digest = hashlib.file_digest(source, "sha256")
    # file_digest 返回后不再依赖 source 的当前位置,调用方仍要负责关闭它。
    return digest.hexdigest()

这个示例表达的是边界,不是说所有文件对象都支持 seek(0)。如果对象来自网络流、管道或某些 socket 包装,它可能只能向前读取;这时应在接口层决定是否允许一次性消费,不能假设摘要函数会自动回退到开头。

文件还应以阻塞模式打开。Python 3.14 起,非阻塞文件会抛出 BlockingIOError;迁移旧代码时如果摘要接口突然在特定文件描述符上失败,先检查打开模式和上游 I/O 封装,而不是重试同一个非阻塞对象。

Python file_digest 的输入模式、文件位置、阻塞要求和调用方关闭责任边界结构图
图2:文件摘要的边界结构;二进制阻塞对象进入 file_digest,文件位置与关闭责任仍属于调用方,非阻塞模式落在异常边界。

需要 HMAC 时传入可调用的摘要工厂

如果任务不是单纯计算公开文件指纹,而是要把文件内容纳入 HMAC,可以传入返回哈希对象的可调用对象。官方示例使用一个已经创建的 HMAC 对象,并通过 lambda 把它交给 file_digest:

import hashlib
import hmac

def file_hmac(path: str, secret: bytes) -> str:
    # HMAC 对象负责密钥语义,file_digest 只负责把文件字节送入它。
    mac = hmac.HMAC(secret, digestmod=hashlib.sha256)
    with open(path, "rb") as source:
        digest = hashlib.file_digest(source, lambda: mac)
    # 返回 HMAC 的十六进制结果;密钥不要写入日志或文章示例的真实配置。
    return digest.hexdigest()

这里的 lambda: mac 返回同一个 HMAC 对象,因此调用完成后 digest 与 mac 指向同一个结果对象。实际业务中应把密钥放在受控的密钥配置中,文件摘要和 HMAC 的用途、密钥管理与校验协议也要分开描述。

从手写循环迁移时检查这五项

检查项迁移前后要保持的语义
输入模式保持二进制读取,不能把文本解码后的字符重新编码来代替原始字节。
算法名称明确使用 sha256、sha512 或约定的构造器,不因异常静默替换算法。
文件位置确认对象从哪里开始读;复用对象时不要把上一次读取留下的位置当成默认起点。
阻塞属性文件对象应处于阻塞模式,非阻塞对象在新版本中可能抛出 BlockingIOError。
资源生命周期file_digest 不替调用方关闭文件;优先用 with 管理 open 返回的对象。

如果只是校验发布包,最小迁移通常就是“保留算法约定、把读取循环替换为 file_digest、继续用 hexdigest 输出”。如果目标是密码存储、抗篡改签名或密钥派生,应该选择对应的密码学接口,不要仅因为摘要 API 方便就把普通哈希直接当作安全方案。

常见问题

file_digest 从 Python 哪个版本开始提供?

官方文档标注它在 Python 3.11 加入。需要支持更老版本时,保留手写的 read() 与 update() 循环,或在项目兼容层中做明确分支。

调用 file_digest 后还能继续读取同一个文件对象吗?

不要依赖它调用后的文件位置或内部状态。文档要求把对象状态视为未知;如果后续还要读取,重新打开文件或在接口边界重新建立明确的读取策略。

为什么一定要用 rb 而不是 r?

摘要针对字节序列。文本模式会引入解码和平台换行语义,可能让参与摘要的内容不再等于磁盘上的原始字节。

file_digest 能代替密码哈希吗?

不能直接这样理解。它是文件或文件类对象的摘要便捷接口;密码存储需要带盐、可调成本和专门的密钥派生方案。

一句话记忆:为一次摘要准备一个二进制、阻塞的文件对象,用明确的算法调用 hashlib.file_digest,结果由调用方格式化,文件仍由调用方关闭。
版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Python itertools.batched 分批消费迭代器的边界Python itertools.batched 分批消费迭代器的边界
上一篇
Python itertools.batched 分批消费迭代器的边界
Python csv newline 参数避免空行的文件处理
下一篇
Python csv newline 参数避免空行的文件处理
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    1014次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    1019次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1143次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1119次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    960次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码