bson.decode_file_iter()可直接读取裸BSON文件,需用'rb'模式打开,返回dict迭代器,自动还原ObjectId、Datetime等类型,但须手动转字符串才能JSON序列化。

用 bson.decode_file_iter() 直接读取 bson 文件,不连数据库
MongoDB 备份出来的 .bson 文件是二进制序列化数据,不是 JSON,不能用 json.load() 或 pickle.load() 打开。Python 的官方 bson 库(来自 pymongo)提供了 bson.decode_file_iter(),它能逐条解析文件里的 BSON 文档,完全脱离 mongod 进程运行。
常见错误是试图用 open(..., 'r') 读文本——BSON 是二进制格式,必须用 'rb' 模式打开;另一个坑是误用 bson.loads()(它只处理单个 BSON 字节串,不是整个文件)。
- 确保已安装
pymongo:pip install pymongo - 文件必须是纯 BSON 格式(如
mongodump生成的 collection.bson),不含额外头尾或元数据 -
bson.decode_file_iter()返回一个迭代器,每项是dict,字段名、嵌套结构、ObjectId、Datetime等类型都按原样还原
遇到 InvalidBSON: invalid object size 怎么办
这个错误几乎总是因为文件不是“裸 BSON”:可能是压缩包(.gz/.bz2)、tar 包、带 metadata 的 mongodump 归档,或者被截断/损坏。MongoDB 官方备份工具 mongodump 默认生成的是 BSON + 元数据 JSON 混合目录结构,单独拎出的 .bson 文件才可直读。
- 先确认文件头:
head -c 4 yourfile.bson | hexdump -C—— 正常 BSON 开头 4 字节应为小端整数,表示第一个文档长度(如1a 00 00 00表示 26 字节) - 如果开头是
1f 8b(gzip)或42 5a(bzip2),需先解压:gunzip -k yourfile.bson.gz - 若文件来自
mongodump --archive,它生成的是归档流,不是单个 BSON 文件,不能直接用decode_file_iter()
提取特定字段或过滤条件时,别在内存里攒全量数据
大 bson 文件(几百 MB 以上)用 list(bson.decode_file_iter(...)) 会瞬间吃光内存。真正要做的只是“提取某几个字段”或“找满足条件的记录”,应该边读边筛。
立即学习“Python免费学习笔记(深入)”;
- 用
for doc in bson.decode_file_iter(f)迭代,对每个doc做轻量判断(如if doc.get('status') == 'active') - 提取字段推荐字典推导或显式构造:
{'id': doc['_id'], 'name': doc.get('name')},避免深拷贝整个doc -
ObjectId和Datetime类型可直接用,但写入 JSON 前得手动转成字符串,否则json.dumps()会报错
import bson
from datetime import datetime
with open('users.bson', 'rb') as f:
for doc in bson.decode_file_iter(f):
if doc.get('created_at', datetime.min) > datetime(2023, 1, 1):
print({'_id': str(doc['_id']), 'email': doc.get('email')})
注意 ObjectId 和时区敏感字段的处理
BSON 中的 ObjectId 和 Datetime 在 Python 里是具体对象,不是字符串。如果你后续要导出为 JSON 或存入其他系统,忽略类型转换会导致序列化失败或时区偏移。
-
ObjectId必须显式转成字符串:str(doc['_id']),否则 JSON 序列化报TypeError: Object of type ObjectId is not JSON serializable -
Datetime对象默认无时区(tzinfo=None),MongoDB 存储的是 UTC 时间;若原始数据含时区,Python 解析后仍为 naive datetime,需用doc['ts'].replace(tzinfo=timezone.utc)显式标注 - 不同 pymongo 版本对
Decimal128支持程度不同,老版本可能直接抛异常,建议加try/except包裹关键字段访问










