DEBUG.WIKI
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
搬瓦工;先看线路,再选 VPS;CN2 GIA · 对应线路套餐;查看线路 →
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS

TTLCache 插入先 OverflowError,随后成员检查又报 NoneType

cachetools 7.2.1 计算到期时间失败可能留下不完整条目,7.2.2 已调整插入顺序。仍需修正计时输入;升级不会让超出日期范围的到期时间合法。

给 TTLCache 插入值时,先抛出日期运算的 OverflowError;异常被捕获后,再做一次成员检查,却变成 datetime 与 NoneType 不能比较的 TypeError。这说明失败的插入可能已经留下了不完整的过期信息。

cachetools 7.2.1 的插入顺序会先修改缓存,再计算 timer() + ttl。自定义计时器返回接近上限的 datetime,即便 TTL 是合法的 timedelta,到期时间也可能超出日期范围。7.2.2 已把到期时间计算提前,当前正式 7.2.4 保留了这项修复。

先修正失败插入的顺序,再处理时间范围

可复现这项边界的输入形状如下,不能把它作为真实生产时钟配置:

from datetime import datetime, timedelta
from cachetools import TTLCache

cache = TTLCache(
    maxsize=1,
    ttl=timedelta(days=1),
    timer=lambda: datetime.max,
)

在这个配置中,任意新值都无法得到可表示的到期时间。升级不会让 datetime.max + timedelta(days=1) 变得合法;它修正的是运算失败时,不应先插入这个新值和空过期链接。

使用 7.2.2 或后续兼容版本以后,应让应用按自己的错误策略处理最初的运算异常,不要只在外层捕获第二次 TypeError。当前 7.2.4 要求 Python 3.10 及以上。旧进程若已包含不完整缓存条目,升级安装包也不会自动重建那一份内存对象。

仅需要持续时间时,保留默认单调时钟

普通的“缓存 60 秒”不需要使用日历日期:

from cachetools import TTLCache

cache = TTLCache(maxsize=1000, ttl=60)

默认计时器是 time.monotonic,这里的 TTL 单位为秒。如果业务必须使用自定义时间类型,则要求插入时的 timer() + ttl 可计算,并能与后续计时值比较。不能把秒数与 datetime、不兼容时区的日期或任意字符串混在一起。

已发生失败插入的旧缓存,不宜继续假定它内部结构仍完整。对可由权威数据重新生成的缓存,可在受控时机换成新的缓存对象,并处理好其他持有者的引用;不要把这当成删除持久业务数据的理由。缓存由多个线程共用时,还需同步读写和替换,cachetools 的缓存类自身并不提供完整线程安全。

验收分成两件事:合法计时输入应能插入、命中和到期;无法计算到期时间的输入应抛出原始异常,同时不留下新键。失败前已有的其他条目也要检查,避免只证明一个空缓存不再报二次异常,就遗漏项目自己的恢复逻辑。