UnicodeDecodeError:'utf8'编解码器无法解码位置3-6的字节:无效数据

52 投票
8 回答
163854 浏览
提问于 2025-04-16 18:38

在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 个回答

4

你看到的这个错误意味着你从远程服务器收到的数据不是有效的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()。)

6

我的解决办法有点搞笑。我从没想过,竟然只需要用UTF-8编码保存一下就能解决问题。我在用Notepad++(版本5.6.8)。一开始我没注意到我保存的时候用了ANSI编码。我是用一个单独的文件来放所有的本地化字典。我在Notepad++的“编码”选项卡下找到了我的解决办法。我选择了“UTF-8无BOM编码”,然后保存。效果非常好。

85

你尝试解析的这个字符串并不是用UTF-8编码的。很可能它是用ISO-8859-1编码的。你可以试试下面的方法:

json.loads(unicode(opener.open(...), "ISO-8859-1"))

这样可以处理JSON消息中可能出现的变音符号。

你应该看看Joel Spolsky写的这篇文章:每个软件开发者绝对必须了解的Unicode和字符集的最低限度知识(没有借口!)。我希望这能帮助你理清一些关于Unicode的问题。

撰写回答