You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python 3.6下shelve的get()与keys()返回结果不一致问题咨询

问题原因
  • shelve本身是对dbm数据库的轻量封装,Python 3.6对应的旧版dbm(尤其是gdbm<1.15版本)存在已知的迭代器缺陷:新增写入的键如果落在新的数据库存储页,keys()、items()这类迭代方法只会读取已加载到内存的旧元数据,不会主动同步磁盘上的最新写入内容,但get()方法是直接按键查询磁盘存储,所以能返回正确结果。
  • 若上一次写入shelve时没有显式调用close()或者sync()方法,最新写入的键会存在操作系统页缓存或者dbm的写入日志中,没有合并到主数据库的元数据索引里,迭代方法读取索引时就会漏掉这部分键。
  • 若该shelve文件是在更高版本Python/其他平台写入的,旧版本dbm解析索引时也可能丢失高序号键的元数据。
解决方法
  • 优先尝试强制同步索引:打开shelve时先调用一次sync()方法,强制将磁盘写入内容同步到内存索引后再读取keys(),示例代码如下:
import shelve
with shelve.open("../../datasets/raw_reviews_translated_helsinki", flag='r') as db:
    db.sync()
    all_keys = list(db.keys())
    print(sorted(map(int, all_keys)))
  • 如果是写入时未正常关闭导致的索引损坏,可以先用flag='w'模式打开一次再关闭,触发dbm的日志合并逻辑,修复索引后后续读取就能拿到全量键。
  • 若以上方法无效,可以用兜底遍历方案:由于你的键是固定步长(100)的增量有序键,可以从最大的可查询到的键开始向上遍历,直到get()返回None为止,收集所有有效键。
  • 长期使用建议升级Python到3.7及以上版本,或者换用sqlite、json等更稳定的存储方案替代shelve,避免底层dbm的实现缺陷。

内容的提问来源于stack exchange,提问作者Artur Siedlecki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 01:42:00