NamedTemporaryFile 不支持自动过期,需手动管理生命周期;推荐将过期时间编码进文件名并用 os.path.getmtime() 判断,或使用 diskcache.Cache 实现 TTL 自动清理。

用 tempfile.NamedTemporaryFile 无法自动过期,得自己管生命周期
Python 标准库的 tempfile 模块只负责“临时”,不负责“时效”。NamedTemporaryFile 创建的文件在进程退出或句柄关闭后就可能被删掉,但不会按时间自动失效。真要带过期时间,必须自己记录创建时间、定期检查、手动清理。
推荐方案:用 os.path.getmtime() + 文件名编码过期时间
最轻量、无依赖的做法是把过期时间直接写进文件名(比如 cache_v2_20241120153000.json),再配合 os.path.getmtime() 判断是否超时。这样不用额外存元数据,也不依赖数据库或 Redis。
- 写缓存时:生成带时间戳的文件名,例如
f"cache_{int(time.time())}.pkl" - 读缓存时:先
os.path.exists(),再os.path.getmtime(path) 判断是否过期(如 1 小时) - 注意:
getmtime是最后修改时间,不是创建时间;如果后续有open(..., "wb").write(),会更新它 —— 所以最好写完立刻os.utime(path, (created, created))锁死时间戳
避免踩坑:shutil.copy2 会覆盖 mtime,改用 shutil.copy 或手动修复
如果你从源文件复制内容到缓存文件(比如下载后缓存),用 shutil.copy2(src, dst) 会把源文件的 mtime 带过来,导致缓存“出生即过期”或“永远不过期”。
- 正确做法一:用
shutil.copy(src, dst)(不复制时间戳) - 正确做法二:复制后立即重设时间戳:
os.utime(dst, (now, now)) - 错误现象:
os.path.getmtime(cache_path)返回的是原始文件的修改时间,而不是你期望的缓存创建时间
更健壮的替代:用 diskcache.Cache(第三方,但极简)
如果项目允许加一个轻量依赖,diskcache 是比手写逻辑更可靠的选择 —— 它原生支持 expire 参数,底层用 SQLite 管理过期键,且线程安全。
立即学习“Python免费学习笔记(深入)”;
import diskcache
cache = diskcache.Cache(directory="/tmp/myapp_cache", expire=3600)
cache.set("user_123", {"name": "Alice"}, expire=1800) # 单条可覆写过期时间
value = cache.get("user_123") # 过期自动返回 None
注意:diskcache 的 expire 是 TTL(秒),不是绝对时间;它会在读取时惰性清理,不占用后台线程 —— 适合大多数 CLI 工具或小型 Web 后端。
真正难处理的是并发写同一缓存键 + 过期边界(比如两个进程同时发现过期、同时重建),这种场景哪怕用 diskcache 也得加锁,别指望文件系统自动帮你串行化。


















