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

Python2.7+pymongo3.6复制Mongo数据遇InvalidBSON错误如何处理?

解决MongoDB非UTF-8字符导致的InvalidBSON错误

这个问题我太熟悉了——在Python 2.7搭配pymongo 3.6的环境下处理MongoDB里的非UTF-8字符,确实容易碰到这种游标迭代时直接崩溃的情况,而且普通的try-except还抓不住,因为错误是pymongo内部解码BSON时抛出来的。我来给你几个可行的解决办法:

方案一:修改BSON解码选项(推荐)

最根本的解决方式是让pymongo在解码非UTF-8字符时自动处理,而不是抛出错误。你可以通过CodecOptions指定字符串解码的错误处理策略,比如替换非法字符或者忽略它们:

from bson.codec_options import CodecOptions

# 创建解码选项,指定非法UTF-8字符的处理方式
# 'replace'会把非法字节替换成�,'ignore'会直接跳过
codec_options = CodecOptions(string_decode_error_handler='replace')

# 给集合绑定这个解码选项
collection1 = db['collection1'].with_options(codec_options=codec_options)
collection2 = db['collection2'].with_options(codec_options=codec_options)

这样设置后,游标迭代时遇到非UTF-8字符会自动处理,不会再抛出InvalidBSON错误,你的原有循环逻辑可以正常运行。

方案二:手动捕获游标迭代时的错误

如果你不想全局修改解码选项,也可以手动迭代游标并捕获每个文档的解码错误,跳过有问题的文档:

import bson.errors

findData = {'isCopied': 0, 'requestDate': {'$lte': today}}
collection1Cursor = collection1.find(findData)

updateArr = []
dataArr = []

while True:
    try:
        doc = next(collection1Cursor)
    except StopIteration:
        # 游标迭代完毕,退出循环
        break
    except bson.errors.InvalidBSON as e:
        # 记录错误信息,跳过当前文档
        print(f"跳过无效BSON文档: {str(e)}")
        continue
    
    # 正常处理文档
    updateArr.append(doc['_id'])
    doc.pop('isCopied', None)
    dataArr.append(doc)

# 注意:pymongo 3.6中insert已废弃,推荐用insert_many,ordered=False等价于continue_on_error=True
collection2.insert_many(dataArr, ordered=False)
collection1.update_many({'_id': {'$in': updateArr}}, {'$set': {'isCopied': 1}})

这个方式能精准跳过有问题的文档,但需要修改你的循环逻辑,用next()手动获取下一个文档并捕获错误。

额外提示

  • pymongo 3.6对Python 2.7的支持是有限的,如果你后续有升级计划,建议转到Python 3,它的字符串处理更友好,能避免很多编码问题。
  • 如果你需要保留原始的非UTF-8字节,可以考虑把对应的字段转成Binary类型存储,但这需要修改数据结构,适合对原始数据有严格要求的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:18:51