UnicodeDecodeError: кодек 'utf8' не может декодировать байты в позиции 3-6: неверные данные
как работает юникод на python2? я просто не понимаю.
здесь я загружаю данные с сервера и разбираю их для 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
Благодарю вас!
EDIT: следующая строка вызывает ошибку: '[{"t":"q","s":"abh\xf6ren"}]'
. \xf6
должен быть декодирован до ö
(абхорен)
Ответы
Ответ 1
Строка, которую вы пытаетесь разобрать как JSON, не кодируется в UTF-8. Скорее всего, он кодируется в ISO-8859-1. Попробуйте следующее:
json.loads(unicode(opener.open(...), "ISO-8859-1"))
Это будет обрабатывать любые умляуты, которые могут попадать в сообщение JSON.
Вы должны прочитать Joel Spolsky Абсолютный минимум Каждый разработчик программного обеспечения Абсолютно, положительно должен знать о Unicode и наборах символов (без отговорок!). Надеюсь, что это прояснит некоторые проблемы, которые возникают вокруг Unicode.
Ответ 2
Мое решение немного смешно. Я никогда не думал, что это будет так же просто, как и с кодеком UTF-8. Я использую notepad ++ (v5.6.8). Я не заметил, что я сохранил его с помощью ANSI кодек изначально. Я использую отдельный файл для размещения всего локализованного словаря. Я нашел свое решение под вкладкой "Кодирование" из моего Notepad ++. Я выбираю "Кодирование в UTF-8 без спецификации" и сохраняю его. Он работает блестяще.
Ответ 3
Ошибка, которую вы видите, означает, что данные, которые вы получаете с удаленного конца, недействительны 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()
.)
Ответ 4
Решение об изменении кодировки в Latin1/ISO-8859-1 решает проблему, которую я наблюдал с помощью html2text.py, как вызывается на выходе tex4ht. Я использую это для автоматического подсчета слов на документах LaTeX: tex4ht преобразует их в HTML, а затем html2text.py разбивает их на чистый текст для дальнейшего подсчета через wc-w. Теперь, если, например, немецкий "Umlaut" приходит через запись в базе данных литературы, этот процесс завершится неудачно, поскольку html2text.py будет жаловаться, например.
UnicodeDecodeError: кодек 'utf8' не может декодировать байты в позиции 32243-32245: недопустимые данные
Теперь эти ошибки впоследствии будут особенно трудно отследить, и, по сути, вы хотите иметь Umlaut в своем разделе ссылок. Простое изменение внутри html2text.py из
data = data.decode(кодирование)
к
data = data.decode( "ISO-8859-1" )
решает эту проблему; если вы вызываете script, используя файл HTML в качестве первого параметра, вы также можете передать кодировку в качестве второго параметра и избавить модификацию.
Ответ 5
Просто в случае, если у кого-то такая же проблема. Я использую vim с YouCompleteMe, не удалось запустить ycmd с этим сообщением об ошибке, что я сделал: export LC_CTYPE="en_US.UTF-8"
, проблема в том, что ушел.
Ответ 6
Вставьте это в свою командную строку:
export LC_CTYPE="en_US.UTF-8"
Ответ 7
Временное обходное решение: unicode(urllib2.urlopen(url).read(), 'utf8')
- это должно работать, если возвращаемое является UTF-8.
urlopen().read()
вернуть байты, и вы должны декодировать их в строки unicode. Также было бы полезно проверить патч от http://bugs.python.org/issue4733
Ответ 8
В вашем android_suggest.py распакуйте этот чудовищный однострочный оператор возврата в one_step_at_a_time. Запишите repr(string_passed_to_json.loads)
где-нибудь, чтобы он мог быть проверен после того, как произойдет исключение. Получите результаты. Если проблема не очевидна, отредактируйте свой вопрос, чтобы показать реестр.