3

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

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

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

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

4

2 回答 2

4

PyMongo 有两种 BSON 实现,一种在 Python 中实现可移植性,另一种在 C 中实现速度。_make_c_string在 Python 版本中会告诉您它未能编码的内容,但显然您正在使用的 C 版本不会。你可以知道你有哪个 BSON 实现import bson; bson.has_c()。我已经提交了PYTHON-533,很快就会修复。

于 2013-06-04T14:01:40.593 回答
1

(回答我自己的问题)

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

代码在bson/__init__.py. 如果要在 utf-8 中编码字符串抛出 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引发 a,则将值包装在 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))
于 2013-05-28T20:53:01.067 回答