UnicodeDecodeError:'utf8'编解码器无法解码位置3-6的字节:无效数据
在Python 2中,Unicode是怎么回事啊?我真搞不懂。
我从服务器上下载数据,然后把它解析成JSON格式。
Traceback (most recent call last):
File "/usr/local/lib/python2.6/dist-packages/eventlet-0.9.12-py2.6.egg/eventlet/hubs/poll.py", line 92, in wait
readers.get(fileno, noop).cb(fileno)
File "/usr/local/lib/python2.6/dist-packages/eventlet-0.9.12-py2.6.egg/eventlet/greenthread.py", line 202, in main
result = function(*args, **kwargs)
File "android_suggest.py", line 60, in fetch
suggestions = suggest(chars)
File "android_suggest.py", line 28, in suggest
return [i['s'] for i in json.loads(opener.open('https://market.android.com/suggest/SuggRequest?json=1&query='+s+'&hl=de&gl=DE').read())]
File "/usr/lib/python2.6/json/__init__.py", line 307, in loads
return _default_decoder.decode(s)
File "/usr/lib/python2.6/json/decoder.py", line 319, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib/python2.6/json/decoder.py", line 336, in raw_decode
obj, end = self._scanner.iterscan(s, **kw).next()
File "/usr/lib/python2.6/json/scanner.py", line 55, in iterscan
rval, next_pos = action(m, context)
File "/usr/lib/python2.6/json/decoder.py", line 217, in JSONArray
value, end = iterscan(s, idx=end, context=context).next()
File "/usr/lib/python2.6/json/scanner.py", line 55, in iterscan
rval, next_pos = action(m, context)
File "/usr/lib/python2.6/json/decoder.py", line 183, in JSONObject
value, end = iterscan(s, idx=end, context=context).next()
File "/usr/lib/python2.6/json/scanner.py", line 55, in iterscan
rval, next_pos = action(m, context)
File "/usr/lib/python2.6/json/decoder.py", line 155, in JSONString
return scanstring(match.string, match.end(), encoding, strict)
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 3-6: invalid data
谢谢你!!
补充一下:下面这个字符串导致了错误:'[{"t":"q","s":"abh\xf6ren"}]'
。这里的\xf6
应该被解码成ö
(abhören)。
8 个回答
你看到的这个错误意味着你从远程服务器收到的数据不是有效的JSON格式。JSON是一种数据格式,通常是用UTF-8编码的,但也可以是UTF-16或UTF-32(这两种编码有大端和小端之分)。你遇到的具体错误表示数据的某部分不是有效的UTF-8编码(而且也不是UTF-16或UTF-32,因为那样会出现不同的错误)。
也许你应该先检查一下从远程服务器收到的实际响应,而不是直接把数据传给json.loads()
。现在,你是把所有的响应数据读成一个字符串,然后假设它是JSON格式。其实,你应该先查看一下响应的内容类型,确保网页确实是声称给你提供JSON,而不是一些错误信息,这些错误信息可不是JSON格式的。
(另外,在检查完响应后,使用json.load()
,把opener.open()
返回的文件对象传给它,而不是把所有数据读成字符串再传给json.loads()
。)
我的解决办法有点搞笑。我从没想过,竟然只需要用UTF-8编码保存一下就能解决问题。我在用Notepad++(版本5.6.8)。一开始我没注意到我保存的时候用了ANSI编码。我是用一个单独的文件来放所有的本地化字典。我在Notepad++的“编码”选项卡下找到了我的解决办法。我选择了“UTF-8无BOM编码”,然后保存。效果非常好。
你尝试解析的这个字符串并不是用UTF-8编码的。很可能它是用ISO-8859-1编码的。你可以试试下面的方法:
json.loads(unicode(opener.open(...), "ISO-8859-1"))
这样可以处理JSON消息中可能出现的变音符号。
你应该看看Joel Spolsky写的这篇文章:每个软件开发者绝对必须了解的Unicode和字符集的最低限度知识(没有借口!)。我希望这能帮助你理清一些关于Unicode的问题。