# 报表文件被覆盖前先核对内容：用 hashlib 计算文件指纹并比对重传版本

## 文档明确的机制

报表在收发、重跑和归档时，仅凭文件名、大小或修改时间，有时无法确认内容是否完全一致。Python 标准库 `hashlib` 提供统一的哈希算法接口，可把字节内容计算成固定长度摘要；同一算法下，摘要不同即可说明参与计算的内容不同。

Python 3.15.2 文档列出的构造函数包括 `md5()`、`sha1()`、`sha224()`、`sha256()`、`sha384()`、`sha512()`、`sha3_256()`、`blake2b()` 等。以 SHA-256 为例：

```python
import hashlib

old = hashlib.sha256()
old.update(b"Nobody inspects")
old.update(b" the spammish repetition")

print(old.hexdigest())
```

文档明确说明，重复调用 `update(data)` 等价于一次性传入拼接后的数据：`m.update(a); m.update(b)` 与 `m.update(a+b)` 等价。因此，大文件不必一次性读入内存，可以按块读取并连续调用 `update()`。最后用 `hexdigest()` 取得十六进制字符串，便于在邮件或其他非二进制环境中交换。

对于文件，`hashlib` 还提供 `file_digest(fileobj, digest, /)`。文档要求 `fileobj` 必须是以二进制只读方式打开的类文件对象，并且处于阻塞模式；它接受内置 `open()` 打开的对象、`BytesIO`、`socket.socket.makefile()` 得到的类似对象等。`digest` 可以是算法名字符串、哈希构造函数，或返回哈希对象的可调用对象。基本用法如下：

```python
import hashlib

def file_sha256(path):
    with open(path, "rb") as f:
        return hashlib.file_digest(f, "sha256").hexdigest()
```

需要特别注意，文档要求调用方负责关闭文件对象；函数返回或抛出异常后，文件对象应被视为处于未知状态。因此，示例用 `with open(...)` 管理生命周期，调用后也不要依赖当前文件位置。

## 团队自行约定的接手建议

以下是团队可自行约定的交接做法，并非 `hashlib` 文档额外提供的产品能力。

第一，报表文件入库、重传或归档前，可约定统一使用同一种算法生成摘要，例如 SHA-256，并在清单中同时保存路径、算法、十六进制摘要和核对时间。不同算法的摘要不能直接比较；即使内容相同，`sha256()` 与 `sha512()` 的结果也不同。

第二，面对较大文件，可按固定字节块循环读取：

```python
import hashlib

def chunked_sha256(path, chunk_size=1024 * 1024):
    h = hashlib.sha256()
    with open(path, "rb") as f:
        for chunk in iter(lambda: f.read(chunk_size), b""):
            h.update(chunk)
    return h.hexdigest()
```

这个流程只做字节级摘要，不解析 CSV、Excel、JSON 或数据库报表的字段含义。它不能替代行数校验、字段校验、编码检查或业务规则验收。

第三，重跑报表时，可把“原始文件、副本、不同时间收到的重传文件”分别计算摘要，再输出不一致文件清单。团队也可自行约定：发现摘要不同后先不要覆盖原文件，而是保留双方文件并排查差异来源。

## 边界与总结

文档明确警告：MD5 和 SHA1 存在已知哈希碰撞弱点。因此，在需要安全防护、抗伪造或对抗性场景下，不应把 MD5/SHA1 当作依据。本文示例采用 SHA-256，但具体合规要求仍应由团队按场景确认。

哈希只能发现参与计算的内容是否变化，不能证明变化原因。摘要不同可能来自内容重跑、传输差异、保存过程变化等，但哈希本身不会指出是哪一个字节、哪一行或哪一个业务字段造成差异。

此外，文档说明某些算法在特殊环境中可能缺失或被阻止，例如少见的“FIPS compliant”Python 构建，或 OpenSSL FIPS 模式排除部分算法；调用不可用构造函数会引发 `ValueError`。`file_digest` 是 Python 3.11 新增能力，若运行环境不是当前文档版本，也应先核对版本支持。

综上，`hashlib` 适合在报表文件被覆盖前建立统一、可复现的内容指纹：用 `sha256()` 等构造函数创建对象，用 `update()` 按拼接语义喂入字节，用 `hexdigest()` 输出十六进制摘要；文件场景可使用二进制只读对象调用 `file_digest()`，并由调用方负责关闭。把文档明确的机制和团队接手规则分开，才能让重传核对流程更清楚，避免把哈希误当成文件解析或业务校验。

## 相关工具

[AI 工作流 ROI 诊断器](/demos/ai-workflow-roi-diagnostic/index.html) · 查看工具的输入要求、输出说明与适用范围。


来源：[报表文件被覆盖前先核对内容：用 hashlib 计算文件指纹并比对重传版本](https://docs.python.org/3/library/hashlib.html)
