UnicodeDecodeError, недійсний байт продовження


257

Чому наведений нижче елемент не працює? і чому це досягає успіху з кодеком "латин-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 навряд чи реально відображатиме таким чином і Unicode, і байтові рядки.)


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
А про евристику дивіться у бібліотеці шардетів.
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. Але чому колись латинь-1 перемагає?
Reihan_amn

11

Якщо ця помилка виникає під час маніпулювання файлом, який щойно відкрився, перевірте, чи відкрили ви його в 'rb'режимі


2
Завдяки цій відповіді, вдалося уникнути помилки, UnicodeDecodeError: «UTF-8» кодек не може декодувати байт 0xd7 в позиції 2024079: неприпустимий продовження байт по soup = BeautifulSoup(open('webpage.html', 'rb'), 'html.parser')
Isaac Філіп

6

Це трапилось і зі мною, коли я читав з .txtфайлу текст, що містить іврит .

Я натиснув: file -> save asі цей файл я зберег як UTF-8кодування


5

Помилка коду utf-8 зазвичай виникає, коли діапазон числових значень перевищує 0 до 127.

Причина підняти цей виняток:

1) Якщо точка коду <128, кожен байт такий самий, як і значення кодової точки. 2) Якщо точка коду дорівнює 128 або більше, рядок Unicode не може бути представлений у цьому кодуванні. (У цьому випадку Python підвищує виняток UnicodeEncodeError.)

Для того, щоб подолати це, у нас є набір кодувань, найпоширенішим є "латинський-1, також відомий як ISO-8859-1"

Отже, точки ISO-8859-1 Unicode 0–255 ідентичні значенням Latin-1, тому для перетворення в це кодування потрібно просто перетворити кодові точки в значення байтів; якщо зустрічається точка коду, більша за 255, рядок не може бути закодований у Latin-1

коли це виняток виникає під час завантаження набору даних, спробуйте скористатися цим форматом

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

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


Привіт і ласкаво просимо до SO! Будь ласка, відредагуйте свою відповідь, щоб переконатися, що вона покращилася стосовно інших відповідей, вже наявних у цьому запитанні.
hongsy


-1

У цьому випадку я спробував виконати .py, який активний шлях / file.sql.

Моє рішення полягало в тому, щоб змінити кодифікацію file.sql на "UTF-8 без BOM", і це працює!

Ви можете це зробити за допомогою Notepad ++.

я залишу частину свого коду.

/ Код /

con = psycopg2.connect (host = sys.argv [1], port = sys.argv [2], dbname = sys.argv [3], user = sys.argv [4], password = sys.argv [5] )

cursor = con.cursor () sqlfile = open (шлях, 'r')

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.