Python 文件校验实战:分块计算 SHA-256,检查下载是否完整

举报
yd_275127495 发表于 2026/10/23 08:57:28 2026/10/23
【摘要】 用 Python 标准库分块计算文件 SHA-256,说明二进制读取、退出码、校验失败排查和可信校验值的边界,并提供可运行示例。

下载压缩包、模型文件或备份后,仅看到“下载完成”还不足以确认内容与发布者提供的文件一致。如果发布页面提供了 SHA-256 校验值,就可以在本地重新计算并比较。本文用 Python 标准库实现一个小工具,重点说明分块读取、二进制模式和校验结果的边界。

一、为什么要分块读取

直接把整个文件读进内存,写法很短,但大文件会占用大量内存。分块方案每次读取 1 MiB,按文件顺序更新同一个哈希对象。这里的 1 MiB 是读取缓冲大小,不是 SHA-256 算法内部的块大小,也不代表任何机器上的最优性能。

保存下面的代码为 check_sha256.py:

import argparse
import hashlib
from pathlib import Path


def sha256_file(path: Path) -> str:
    digest = hashlib.sha256()
    with path.open("rb") as stream:
        for block in iter(lambda: stream.read(1024 * 1024), b""):
            digest.update(block)
    return digest.hexdigest()


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("file", type=Path)
    parser.add_argument("expected", help="发布者提供的 SHA-256 值")
    args = parser.parse_args()
    expected = args.expected.strip().lower()
    if len(expected) != 64 or any(c not in "0123456789abcdef" for c in expected):
        parser.error("expected 必须是 64 位十六进制字符串")
    try:
        actual = sha256_file(args.file)
    except OSError as error:
        parser.exit(2, f"无法读取文件:{error}\n")
    print(f"实际 SHA-256:{actual}")
    matched = actual == expected
    print("校验通过" if matched else "校验失败,请检查文件与校验值")
    raise SystemExit(0 if matched else 1)

二进制模式 rb 保留文件原始字节,避免文本解码或换行处理影响结果。循环读到空字节串时结束,因此空文件也会得到确定的摘要。所有数据块必须更新同一个 digest;逐块计算哈希后再拼接字符串,并不是整个文件的 SHA-256。

二、运行与自查

在文件下载完毕、没有其他程序继续写入后运行:

python3 check_sha256.py ./package.zip 发布页面给出的64位SHA256值

上面最后一个参数需要替换为真实校验值,不包含文件名。脚本以退出码 0 表示一致、1 表示不一致、2 表示参数或读取错误,便于接入后续自动化。校验失败时,先核对版本、文件名和期望值,再检查下载是否中断,不要直接覆盖期望值来“修复”。

本文核心分块函数已用三类输入验证:空文件、五字节的 hello,以及 2700000 字节的多块数据;计算结果均与同一内容一次性计算的结果一致。测试只验证实现结果,没有进行性能基准测试。

三、相同摘要能说明什么

校验值应该来自可信发布页面或可信校验清单。如果文件和校验值都来自同一个不可信来源,二者一致也不能证明软件安全。摘要比较用于检查内容是否匹配;确认发布者身份还需要可信渠道或签名验证。文件在计算期间发生变化,也会让结果失去明确含义,备份场景应对稳定副本计算摘要。

参考:Python 3.12 官方文档,标准库参考中的 hashlib(安全哈希与消息摘要)章节。

本文由 AI 辅助撰写,示例的核心分块函数已在本地运行验证。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。