如何找到导致bson.errors.InvalidStringData的值

时间:2013-05-15 18:35:27

标签: mongodb exception pymongo bson

我有一个从各种来源读取数据并将它们存储在MongoDB中的系统。我收到的数据已经在utf-8或unicode中正确编码。如果您愿意,文档与架构有很大关系并且差异很大。

文档的字段值是纯二进制数据,就像JPEG图像一样。我知道如何在bson.binary.Binary对象中包装该值以避免bson.errors.InvalidStringData异常。

有没有办法告诉文件的哪一部分让pymongo司机提出bson.errors.InvalidStringData,或者我是否必须尝试转换每个字段才能找到它?

(+如果偶然的二进制对象碰巧是有效的unicode字符串或utf-8,它将被存储为字符串,这没关系)

2 个答案:

答案 0 :(得分:3)

PyMongo有两个BSON实现,一个用Python实现可移植性,一个用C实现速度。 Python版本中的_make_c_string将告诉您它编码失败的原因,但C版本(显然是您正在使用的版本)却没有。您可以使用import bson; bson.has_c()确定您拥有的BSON实施方式。我已经提交了PYTHON-533,很快就会修复。

答案 1 :(得分:0)

(回答我自己的问题)

您无法从异常中分辨出来,并且需要对驱动程序进行一些重写才能支持该功能。

代码位于bson/__init__.py。如果要在utf-8中编码,则如果string抛出UnicodeError,则会有一个名为_make_c_string的函数引发InvalidStringData。相同的功能用于键和值,它们都是字符串。

换句话说,在代码的这一点上,驱动程序不知道它是在处理密钥还是值。

违规数据 作为原始字符串传递给异常的构造函数,但由于某种原因我不明白,它并不是来自驱动程序。

>>> bad['zzz'] = '0\x82\x05\x17'
>>> try:
...     db.test.insert(bad)
... except bson.errors.InvalidStringData as isd:
...     print isd
...
strings in documents must be valid UTF-8

但这并不重要:无论如何,你必须查找该值的键。

最好的方法是迭代值,尝试在utf-8中解码它们。如果引发UnicodeDecodeError,请将值包装在Binary对象中。

有点像这样:

try:
    #This code could deal with other encodings, like latin_1
    #but that's not the point here
    value.decode('utf-8')
except UnicodeDecodeError:
    value = bson.binary.Binary(str(value))