diskcache是Python生态中唯一开箱即用、线程安全、带过期、可持久化、支持大小限制且不依赖外部服务的本地缓存方案;它基于SQLite+文件混合存储,提供字典式接口,支持自动淘汰、原子写入和主动/惰性过期清理。

用 diskcache,别自己封装字典 + 时间戳逻辑。 它是目前 Python 生态中唯一开箱即用、线程安全、带过期、可持久化、支持大小限制且不依赖外部服务的本地缓存方案。自研方案在并发写入、磁盘清理、异常恢复等环节极易出错。
为什么不用 shelve 或手动 pickle + os.path?
这些方案看似“本地”“持久”,但实际踩坑密集:
-
shelve不支持并发读写(即使加锁也难保数据一致),多进程下容易损坏数据库文件 - 手动序列化 + 文件管理无法自动处理过期项,得自己扫描、删除、压缩,IO 开销大且易漏删
- 没有内置淘汰策略,
maxsize需自行维护,缓存膨胀后内存和磁盘双爆 - 不支持原子性写入,程序崩溃时可能留下半写入的脏文件
diskcache.Cache 的关键参数与典型用法
它把缓存抽象为一个类似字典的接口,但底层是 SQLite + 文件混合存储,兼顾速度与可靠性:
-
directory:指定缓存根目录(必须存在),建议用绝对路径,如"/tmp/myapp_cache" -
size_limit:总磁盘用量上限(字节),超限时自动触发 LRU 清理;设为2**30(1GB)较常见 -
eviction_policy:默认"least-recently-stored",也可选"least-recently-used"(需启用memoize装饰器才记录访问时间) -
timeout:SQLite 写锁等待超时(秒),高并发场景建议设为5以上,避免死等
示例:
from diskcache import Cache
<p>cache = Cache(
directory='/var/cache/myapp',
size_limit=2**30,
timeout=5
)</p><p>cache.set('user:1001', {'name': 'Alice', 'role': 'admin'}, expire=3600)
data = cache.get('user:1001') # 命中返回值,未命中返回 None
</p>
如何避免 diskcache 在高频小写入场景变慢?
SQLite 的 WAL 模式虽已启用,但频繁 set() 仍会引发大量小事务。优化要点:
- 批量操作优先用
cache.update({k1: v1, k2: v2}),比循环set快 3–5 倍 - 对只读为主的场景,可关闭写前日志:
cache = Cache(..., disk_min_file_size=0)(慎用,牺牲崩溃安全性) - 避免缓存超大对象(>1MB),否则序列化/反序列化和磁盘 IO 成瓶颈;大文件建议存路径,缓存元数据
- 不要在循环内反复创建
Cache实例——它是线程安全的,应全局复用
真正难处理的不是“怎么存”,而是“什么时候删干净”:diskcache 的 expire 是惰性检查(读时触发),若某 key 长期不被访问,过期项会一直占磁盘。生产环境需定期调用 cache.expire() 主动清理,比如在应用启动或低峰期 cron 执行。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











