UnicodeDecodeError: кодек «utf8» не может декодировать байты в позиции 3-6: неверные данные - PullRequest
51 голосов
/ 31 мая 2011

как работает юникод на 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

спасибо !!

РЕДАКТИРОВАТЬ: следующая строка вызывает ошибку: '[{"t":"q","s":"abh\xf6ren"}]'. \xf6 должно быть расшифровано до ö (abhören)

Ответы [ 8 ]

83 голосов
/ 31 мая 2011

Строка, которую вы пытаетесь проанализировать как JSON, не кодируется в UTF-8. Скорее всего, это закодировано в ISO-8859-1. Попробуйте следующее:

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

Это обработает все умлауты, которые могут попасть в сообщение JSON.

Вы должны прочитать Джоэл Спольски Абсолютный минимум, который должен знать каждый разработчик программного обеспечения Абсолютно, положительно, необходимо знать о Unicode и наборах символов (без оправданий!) . Я надеюсь, что это прояснит некоторые проблемы, которые у вас возникли вокруг Unicode.

6 голосов
/ 11 июня 2012

Мое решение немного забавно. Я никогда не думал, что это будет так же просто, как сохранить с кодом UTF-8. Я использую notepad ++ (v5.6.8). Я не заметил, что я сохранил его с ANSI кодек изначально. Я использую отдельный файл для размещения всего локализованного словаря. Я нашел свое решение на вкладке «Кодировка» в блокноте ++. Я выбираю «Кодирование в UTF-8 без спецификации» и сохраняю его. Работает блестяще.

4 голосов
/ 31 мая 2011

Ошибка, которую вы видите, означает, что данные, полученные с удаленного конца, не являются допустимыми в формате 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().)

3 голосов
/ 22 августа 2013

Решение изменить кодировку на 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")

решает эту проблему;если вы вызываете скрипт, используя HTML-файл в качестве первого параметра, вы также можете передать кодировку в качестве второго параметра и сохранить модификацию.

1 голос
/ 04 июня 2016

Вставьте это в вашу командную строку:

export LC_CTYPE="en_US.UTF-8" 
1 голос
/ 10 апреля 2014

На всякий случай у кого-то такая же проблема.Я использую vim с YouCompleteMe , не удалось запустить ycmd с этим сообщением об ошибке, что я сделал: export LC_CTYPE="en_US.UTF-8", проблема исчезла.

0 голосов
/ 31 мая 2011

В вашем android_suggest.py разбейте этот чудовищный однострочный оператор возврата на куски one_step_at_a_time. Зарегистрируйте repr(string_passed_to_json.loads) где-нибудь, чтобы его можно было проверить после возникновения исключения. Глазное яблоко результаты. Если проблема не очевидна, отредактируйте свой вопрос, чтобы показать отчет.

0 голосов
/ 31 мая 2011

Временное решение: unicode(urllib2.urlopen(url).read(), 'utf8') - это должно работать , если возвращает UTF-8.

urlopen().read() возвращает байты, и вам необходимо декодировать их в строки Unicode.Также было бы полезно проверить патч от http://bugs.python.org/issue4733

...