
本文介绍如何在多进程场景下,通过合理设置 shelve 的打开模式(如 'r' 只读、'c' 读写创建)并配合显式关闭机制,避免文件锁冲突,同时支持单进程初始化缓存、多进程并发读取的安全缓存方案。
本文介绍如何在多进程场景下,通过合理设置 shelve 的打开模式(如 `'r'` 只读、`'c'` 读写创建)并配合显式关闭机制,避免文件锁冲突,同时支持单进程初始化缓存、多进程并发读取的安全缓存方案。
在 Python 应用中,shelve 是一个轻量级持久化键值存储工具,常被用作本地缓存。但其底层依赖 dbm(如 dumbdbm、bsddb 或 sqlite3 后端),多数实现不支持真正的并发读写——若多个进程同时以写模式(如 'c' 或 'w')打开同一 shelf 文件,极易触发 OSError: [Errno 11] Resource temporarily unavailable 或“locked file”错误。
✅ 正确的多进程访问策略
核心原则是:写操作严格串行化(仅限单进程初始化/重建),读操作完全并发化(所有后续进程均以只读方式打开)。具体实现如下:
-
初始化/重建缓存时:使用
flag='c'(默认)或'n'(强制新建),确保可读写,并在操作完成后显式调用.close():
Secure Python Code Sandbox下载安全 Python 代码沙箱:在隔离的沙箱中执行任意 Python 代码,预装 requests、NumPy、pandas 库。返回 stdout、stderr。
import shelve # 单次构建缓存(例如首次运行或校验失败后) with shelve.open('cache.db', flag='c') as db: db['config'] = {'version': '1.2'} db['data'] = list(range(1000)) # 自动关闭,也可手动 db.close() -
常规读取时:所有其他进程必须使用
flag='r'显式声明只读模式:立即学习“Python免费学习笔记(深入)”;
# 多个进程可同时安全执行以下代码 try: with shelve.open('cache.db', flag='r') as db: value = db.get('config', {}) print("Cache version:", value.get('version')) # 自动关闭,释放文件句柄 except PermissionError: # 极少数后端(如某些 dbm 实现)可能对 'r' 模式权限敏感,建议统一用 'c' + 异常兜底 pass
⚠️ 关键注意事项
-
flag='r'是避免锁冲突的必要条件,它禁止任何写入操作,且大多数dbm后端在此模式下不加写锁; - 切勿在多进程环境中混用
'c'或'w'—— 即使逻辑上“当前无写入”,OS 层仍可能因文件句柄竞争导致阻塞或崩溃; - 若需运行时动态升级为可写(极少见),必须先
close()当前只读 shelf,再以'c'重新打开(但此操作本身不具备原子性,不推荐用于并发环境); - 推荐搭配
shelve.open(..., writeback=False)(默认)以减少内存占用;如需自动同步修改,务必注意writeback=True会显著增加内存开销且仍不解决并发问题; - 对于高并发或复杂查询需求,应考虑升级至 SQLite(原生支持 WAL 并发)或 Redis 等专业缓存系统。
✅ 总结
shelve 本身不是为多写设计的工具,但通过「单点写入 + 多点只读」的明确分工,配合 flag='r' 和 with 语句自动资源管理,即可在简单缓存场景中安全落地。牢记:只读模式是并发读取的基石,显式关闭是资源可靠释放的保障。

















