UnicodeDecodeError, недопустимый байт продолжения


257

Почему ниже пункт не работает? и почему это удается с кодеком "latin-1"?

o = "a test of \xe9 char" #I want this to remain a string as this is what I am receiving
v = o.decode("utf-8")

результаты в:

 Traceback (most recent call last):  
 File "<stdin>", line 1, in <module>  
 File "C:\Python27\lib\encodings\utf_8.py",
 line 16, in decode
     return codecs.utf_8_decode(input, errors, True) UnicodeDecodeError:
 'utf8' codec can't decode byte 0xe9 in position 10: invalid continuation byte

Ответы:


247

В двоичном виде 0xE9 выглядит так 1110 1001. Если вы прочтете про UTF-8 в Википедии , вы увидите, что за таким байтом должны следовать две формы 10xx xxxx. Так, например:

>>> b'\xe9\x80\x80'.decode('utf-8')
u'\u9000'

Но это только механическая причина исключения. В этом случае у вас есть строка, которая почти наверняка закодирована в латинском 1. Вы можете увидеть, как UTF-8 и латинский 1 выглядят по-разному:

>>> u'\xe9'.encode('utf-8')
b'\xc3\xa9'
>>> u'\xe9'.encode('latin-1')
b'\xe9'

(Обратите внимание, что я использую смесь представлений Python 2 и 3. Здесь ввод действителен в любой версии Python, но ваш интерпретатор Python вряд ли на самом деле будет отображать строки как в Юникоде, так и в байтах).


2
Спасибо (и тому, кто ответил), я ошибочно полагал, что символы до 255 будут напрямую преобразованы.
RuiDC

Я получаю UnicodeEncodeError: 'ascii' codec can't encode characters in position 2-3: ordinal not in range(128)ошибку при использовании.encode(latin-1)
Шива

234

У меня была такая же ошибка, когда я пытался открыть CSV-файл методом pandas read_csv.

Решением было изменить кодировку на 'latin-1':

pd.read_csv('ml-100k/u.item', sep='|', names=m_cols , encoding='latin-1')

1
Это действительно решает проблему, хотя? Разве это не просто говорит пандам игнорировать байт, понижая его до менее сложного стиля кодирования?
Ю Чен

61

Это недействительный UTF-8. Этот символ является острым символом в ISO-Latin1, поэтому он успешно работает с этим набором кодов.

Если вы не знаете кодовый набор, в который вы получаете строки, у вас возникли проблемы. Было бы лучше, если бы для вашего протокола / приложения был выбран один кодовый набор (надеюсь, UTF-8), и тогда вы просто отклонили бы те, которые не были декодированы.

Если вы не можете этого сделать, вам понадобится эвристика.


2
А для эвристики, см. Библиотеку chardet.
mlissner

44

Потому что UTF-8 является многобайтовым и нет символа, соответствующего вашей комбинации \xe9 плюс следующий пробел.

Почему он должен иметь успех как в utf-8, так и в latin-1?

Вот как должно быть то же предложение в utf-8:

>>> o.decode('latin-1').encode("utf-8")
'a test of \xc3\xa9 char'

Latin-1 - это семейство однобайтовых кодировок, поэтому все в нем должно быть определено в UTF-8. Но почему когда-нибудь Latin-1 выигрывает?
Reihan_amn

11

Если эта ошибка возникает при манипулировании файлом, который был только что открыт, проверьте, открыли ли вы его в 'rb'режиме


2
Благодаря этому ответу удалось избежать ошибки UnicodeDecodeError: кодек «utf-8» не может декодировать байт 0xd7 в позиции 2024079: недопустимый байт продолжения by soup = BeautifulSoup(open('webpage.html', 'rb'), 'html.parser')
Исаак Филипп

6

Это случилось и со мной, когда я читал текст, содержащий иврит, из .txtфайла.

Я нажал: file -> save asи я сохранил этот файл в UTF-8кодировке


5

Ошибка кода utf-8 обычно возникает, когда диапазон числовых значений превышает от 0 до 127.

причина поднять это исключение:

1) Если кодовая точка <128, каждый байт совпадает со значением кодовой точки. 2) Если кодовая точка 128 или больше, строка Unicode не может быть представлена ​​в этой кодировке. (В этом случае Python вызывает исключение UnicodeEncodeError.)

Чтобы преодолеть это, у нас есть набор кодировок, наиболее широко используемым является «Latin-1, также известный как ISO-8859-1»

Таким образом, точки Unicode ISO-8859-1 0–255 идентичны значениям Latin-1, поэтому преобразование в эту кодировку просто требует преобразования кодовых точек в байтовые значения; если кодовая точка больше 255, строка не может быть закодирована в Latin-1

когда это исключение возникает при попытке загрузить набор данных, попробуйте использовать этот формат

df=pd.read_csv("top50.csv",encoding='ISO-8859-1')

Добавьте метод кодирования в конце синтаксиса, который затем принимает для загрузки набора данных.


Привет и добро пожаловать на ТАК! Пожалуйста, измените свой ответ, чтобы убедиться, что он улучшает другие ответы, уже присутствующие в этом вопросе.
hongsy


-1

В этом случае я попытался выполнить .py, который активен путь / file.sql.

Мое решение состояло в том, чтобы изменить кодификацию файла.sql на «UTF-8 без спецификации», и это работает!

Вы можете сделать это с помощью Notepad ++.

Я оставлю часть моего кода.

/ Код /

con = psycopg2.connect (host = sys.argv [1], port = sys.argv [2], dbname = sys.argv [3], user = sys.argv [4], пароль = sys.argv [5] )

cursor = con.cursor () sqlfile = open (путь, 'r')

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.