pymongo读取MongoDB存二进制的string字段时如何禁用utf8解码
报错原因
你遇到的InvalidBSON报错是因为pymongo默认会将MongoDB的String类型字段按UTF-8编码自动解码为Python的str类型,而你在String字段中实际存储了二进制数据(报错信息中的0x8b是gzip压缩格式的标准起始字节,推测你的content为gzip压缩后的内容),不符合UTF-8编码规则,触发解码失败。
解决方案
方法1:指定字符串解码规则为latin-1,无损失获取原始字节
该方案兼容你的运行环境,无需修改现有存量数据,操作最简便:
初始化MongoClient时配置unicode_decode_error_handler为latin-1,latin-1是单字节编码,所有字节都可以被正常解码,不会触发报错,之后你可以将字符串重新编码为latin-1得到原始二进制数据:
from pymongo import MongoClient from pymongo.codec_options import CodecOptions mongo_client = MongoClient( 'mongodb://admin:pass@127.0.0.1:27017/web_cache?authSource=admin', codec_options=CodecOptions(unicode_decode_error_handler='latin-1') ) collection = mongo_client['web_cache']['pages'] for x in collection.find({"status" : 1},{ "_id": 0, "url": 1, "effective_url": 1, "content" : 1, "Content-Type" : 1 }): # 重新编码得到content的原始二进制数据 content_bytes = x['content'].encode('latin-1') print(content_bytes) # 若为gzip压缩内容可直接解压 # import gzip # origin_content = gzip.decompress(content_bytes).decode('utf-8') break
方法2:后续新数据建议存储为BSON二进制类型
如果后续还要写入新的content数据,建议直接封装为BSON Binary类型存储,从根源避免同类解码问题,写入示例:
from bson.binary import Binary # 写入二进制数据时直接封装为Binary类型 content = b'your binary content' collection.insert_one({ 'url': 'xxx', 'content': Binary(content), 'status': 1 })
按该方式存储的content字段,读取时pymongo会直接返回bytes类型,不会触发解码报错。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

