Pydantic ByteSize 显示 1024.0KiB,实际却还不到 1MiB
human_readable 先选择单位再舍入,临界值可能显示成 1024.0KiB。准确字节数与显示文本分别保存,限额判断不解析舍入后的字符串。
ByteSize(1048575).human_readable() 显示成 1024.0KiB,而不是看起来更自然的下一单位;十进制模式下,999999 字节也可能显示 1000.0KB。先区分实际字节数与已经舍入的显示文本,不要据此把文件大小改成更大的整数。
Pydantic 2.14.1 的处理先按未舍入的数值选择单位,再格式化为一位小数。略低于 1024 KiB 的数仍选择 KiB,但显示阶段会四舍五入到 1024.0;函数没有在舍入后再次提升单位。数值本身并没有变成整整 1 MiB。
配额判断始终用原始字节数
如果这份大小用于限额、计费或签名,不应解析 human_readable() 的返回文本来还原数值。可以把准确值和展示值分别传递:
from pydantic import ByteSize
size = ByteSize(1048575)
payload = {
"bytes": int(size),
"display": size.human_readable(),
}
bytes 作为准确值使用,display 只负责给人阅读。这里直接构造 ByteSize 是展示已知整数;接口收到带单位字符串时,仍应通过原来的模型验证流程解析并执行业务约束。
如果界面不能接受 1024.0KiB 这种边界呈现,最简单的替代是显示准确字节数,例如 f"{int(size)} B",或者采用项目已经定义的单位格式器。新的格式规则需要明确单位基数、精度以及舍入后是否提升单位;不能只把特定字符串替换为 1.0MiB,再对其他边界继续沿用不同规则。
显示成下一单位不代表达到门槛
999999 字节与 1000000 字节不同,1048575 字节与 1048576 字节也不同。前者在一位小数的显示中可能接近边界,但限额比较仍应使用整数。二进制 KiB 的基数是 1024,十进制 KB 的基数是 1000,切换 decimal=True 会改变整套单位含义,不是只换个拼写。
截至 2026 年 10 月 26 日,2.14.1 正式实现仍先选单位后舍入。验收自己的显示调整时,覆盖单位门槛前后、零与较大值,并比较原始 bytes 未改变;不能只检查界面字符串终于好看,而让配额或接收协议跟着发生变化。


