Python Ring缓存库:如何让ring.dict忽略None值不缓存
ring.dict 配置None值跳过缓存写入的实现方案
核心实现逻辑
Ring 缓存的装饰器流程内置了写入拦截能力,不需要修改dict后端的底层存储逻辑,只需在装饰器初始化时传入自定义判定规则,即可实现需求:
- 装饰器会在被装饰函数执行完成拿到返回结果后,先执行自定义的拦截判定
- 当判定条件命中时,直接跳过本次缓存写入操作,不把结果存入底层字典存储
- 只有判定通过的非None返回值,才会走正常的缓存读写流程
具体配置代码
- 初始化ring.dict存储实例:
from ring.dict import DictRing # 初始化内存字典缓存实例,根据实际业务调整存储字典和key前缀 ring = DictRing(dict={}, key_prefix="user_cache") - 装饰业务函数时传入None值跳过规则:
# ttl按业务需求调整,value_skip为内置的写入拦截回调 @ring(ttl=3600, value_skip=lambda return_value: return_value is None) def get_user_detail(user_id: int): # 业务逻辑示例:查询用户信息,查不到时返回None if user_id not in user_database: return None return {"user_id": user_id, "user_name": "测试用户"}
执行行为说明
- 当被装饰函数返回None时,
value_skip回调会判定返回True,系统直接把None返回给调用方,不会在底层缓存字典中写入任何对应键值对 - 相同参数下后续再次调用函数时,因为缓存中没有对应键,会重新执行原函数逻辑,不会出现“曾经返回过None就永久缓存None”的问题
- 当被装饰函数返回非None结果时,
value_skip回调判定返回False,系统会把结果正常写入缓存,后续相同参数的调用会直接命中缓存返回结果,不重复执行原函数
常见注意事项
- 拦截判定一定要用
return_value is None做严格判空,不要用not return_value的布尔判定,否则会把空字符串、数字0、空列表、空字典这类合法的非None返回值误判为跳过写入的对象,违背需求预期 - 不要在装饰器外层手动包裹逻辑做None值删除,比如拿到None返回值后手动删除缓存键,这种实现存在并发竞态问题,Ring内置的
value_skip是在写入流程的原子节点做拦截,不存在该问题 - 若使用的Ring版本低于0.6.0,没有内置
value_skip参数,可通过重写DictRing的写入钩子方法实现相同逻辑:在写入流程开始时判断值是否为None,如果是则直接终止写入流程,效果和内置参数完全一致
内容的提问来源于stack exchange,提问作者andnik
相关产品推荐
相关产品推荐

