lru_cache不算“本地缓存”是因为它仅驻留在进程内存中,进程退出即丢失,不落盘、不跨进程、不支持持久化;真正本地缓存需结合joblib、diskcache等落盘方案。

不能直接用 functools.lru_cache 实现“本地缓存”——它只在内存中缓存,进程退出就丢,不落盘。 如果你期望函数结果重启后还能复用,得自己加持久化层,lru_cache 只能帮你省掉重复计算,不是数据库替代品。
为什么 lru_cache 不算“本地缓存”?
它的缓存完全驻留在 Python 进程的内存里,生命周期和函数对象绑定。同一函数多次调用可命中,但程序一关、解释器一重启,所有缓存全清空。它不写文件、不连 SQLite、也不碰磁盘路径。
常见误用场景:
- 以为加了
@lru_cache就能避免重复爬网页或查数据库 —— 实际只对同一进程内重复调用有效 - 在 Flask/FastAPI 的多 worker 模式下依赖它共享结果 —— 每个 worker 有独立缓存,互不通信
- 缓存大对象(如 pandas DataFrame)导致内存持续上涨,没设
maxsize
怎么让 lru_cache 安全又实用?
它真正适合的是纯计算型、输入确定、输出稳定、且调用密集的函数。比如解析固定格式字符串、递归斐波那契、小规模 JSON schema 校验。
实操建议:
- 显式设置
maxsize,别用默认的128或None(无限),尤其当参数组合多时:@lru_cache(maxsize=512) - 确保参数可哈希:不能传
list、dict、set等不可哈希类型,会直接报TypeError: unhashable type;可改用tuple或frozenset - 用
cache_info()监控命中率:my_func.cache_info()返回CacheInfo(hits=12, misses=3, maxsize=512, currsize=3) - 敏感函数(如含时间戳、随机数)别缓存,或提前把“可变部分”剥离出去
想真正落地“本地缓存”,该接什么?
如果确实需要跨进程、跨启动的本地缓存,lru_cache 得配合外部存储。常见轻量方案:
- 用
joblib.Memory:自动序列化参数/返回值到指定目录,支持cachedir='./cache',且能按源码变更自动失效 - 用
diskcache.Cache(需pip install diskcache):线程安全、支持过期、可查大小,API 类似dict:cache['key'] = result - 自己封装:用
pickle+os.path.join(cache_dir, hashlib.md5(repr(args).encode()).hexdigest())手动存取,但要处理并发写、异常中断、清理逻辑
注意:所有落盘方案都要考虑参数是否真的“稳定”——比如传了 datetime.now() 作参数,每次哈希都不同,缓存形同虚设。
最常被忽略的一点:缓存键的生成逻辑比缓存本身更关键。哪怕用了 diskcache,只要参数含未标准化的时间、浮点误差、或临时对象 ID,缓存就几乎不命中。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











