我正在尝试将包含非ascii字符的传入字节字符串转换为有效的utf-8字符串,以便我可以将其转储为json。
b = '\x80'
u8 = b.encode('utf-8')
j = json.dumps(u8)
我希望j为'\ xc2 \ x80',但我得到:
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0: ordinal not in range(128)
在我的情况下,'b'来自mysql通过谷歌协议缓冲区,并填写了一些blob数据。
有什么想法吗?
编辑: 我有以太网帧作为blob存储在mysql表中(请大家,请保持主题,不要讨论为什么表中有数据包)。表格排序是utf-8,db层(sqlalchemy,non-orm)正在抓取数据并创建结构(谷歌协议缓冲区),它将blob存储为python“str”。在某些情况下,我直接使用协议缓冲区,没有任何问题。在其他情况下,我需要通过json公开相同的数据。我注意到的是,当json.dumps()做了它的事情,'\ x80'可以用无效的unicode char替换(\ ufffd iirc)
答案 0 :(得分:9)
您需要检查您正在使用的软件API的文档。 BLOB是首字母缩略词: BINARY 大对象。
如果您的数据实际上是二进制的,那么将其解码为Unicode的想法当然是无稽之谈。
如果它实际上是文本,则需要知道使用哪种编码将其解码为Unicode。
然后你使用json.dumps(a_Python_object)
...如果你自己编码为UTF-8,json
会再次解码它:
>>> import json
>>> json.dumps(u"\u0100\u0404")
'"\\u0100\\u0404"'
>>> json.dumps(u"\u0100\u0404".encode('utf8'))
'"\\u0100\\u0404"'
>>>
关于latin1
:
u'\x80'
是一个无用的无意义的C1控制字符 - 编码极不可能是Latin-1。 Latin-1是“陷阱和妄想” - 所有8位字节都被解码为Unicode而不会引发异常。不要混淆“作品”和“不引起异常”。
答案 1 :(得分:6)
使用b.decode('name of source encoding')
获取unicode版本。当我学到它时,这对我来说是令人惊讶的。例如:
In [123]: 'foo'.decode('latin-1')
Out[123]: u'foo'
答案 2 :(得分:2)
我认为你要做的是解码某些编码的字符串对象。你知道编码是什么吗?获取unicode对象。
unicode_b = b.decode('some_encoding')
然后使用utf_8编码将unicode对象重新编码回字符串对象。
b = unicode_b.encode('utf_8')
使用unicode对象作为翻译器,不知道字符串的原始编码是什么,我无法确定,但转换可能不会按预期进行。 unicode对象不用于将一种编码的字符串转换为另一种编码。假设您知道编码是什么,我会使用unicode对象,如果您不知道编码是什么,那么在没有试验和错误的情况下确实没有找到方法,然后转换回编码的字符串时你想要一个字符串对象。