UnicodeDecodeError Загрузка с помощью sqlalchemy

Я запрашиваю базу данных MySQL с sqlalchemy и получаю следующую ошибку:

UnicodeDecodeError: 'utf8' codec can't decode bytes in position 498-499: unexpected end of data 

Столбец в таблице был определен как Unicode(500) поэтому эта ошибка подсказывает мне, что есть запись, которая была усечена, потому что она была длиннее 500 символов. Есть ли способ справиться с этой ошибкой и все еще загружать запись? Есть ли способ найти ошибочную запись и удалить ее, кроме попытки загрузить каждую запись по одному (или в партиях), пока я не получу ошибку?

3 Solutions collect form web for “UnicodeDecodeError Загрузка с помощью sqlalchemy”

Короче говоря, вы должны изменить:

 Unicode(500) 

чтобы:

 Unicode(500, unicode_errors='ignore', convert_unicode='force') 

(Код Python 2 следует, но принципы выполняются в python 3, только некоторые из них будут отличаться.)

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

 >>> u = u'ABCDEFGH\N{TRADE MARK SIGN}' >>> u u'ABCDEFGH\u2122' >>> print(u) ABCDEFGH™ >>> s = u.encode('utf-8') >>> s 'ABCDEFGH\xe2\x84\xa2' >>> truncated = s[:-1] >>> truncated 'ABCDEFGH\xe2\x84' >>> truncated.decode('utf-8') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/Users/cliffdyer/.virtualenvs/edx-platform/lib/python2.7/encodings/utf_8.py", line 16, in decode return codecs.utf_8_decode(input, errors, True) UnicodeDecodeError: 'utf8' codec can't decode bytes in position 8-9: unexpected end of data 

Однако Python предоставляет различные факультативные режимы обработки ошибок декодирования. Поднятие исключения по умолчанию, но вы также можете обрезать текст или преобразовать некорректную часть строки в официальный символ замены юникода.

 >>> trunc.decode('utf-8', errors='replace') u'ABCDEFGH\ufffd' >>> trunc.decode('utf-8', errors='ignore') u'ABCDEFGH' 

Это именно то, что происходит в обработке столбцов.

Глядя на классы Unicode и String в sqlalchemy / sql / sqltypes.py , похоже, что есть аргумент unicode_errors который вы можете передать конструктору, который передает его значение до аргумента ошибок в кодере. Также есть примечание, что вам нужно будет установить convert_unicode='force' чтобы он работал.

Таким образом, Unicode(500, unicode_errors='ignore', convert_unicode='force') должен решить вашу проблему, если вы в порядке с усечением концов ваших данных.

Если у вас есть некоторый контроль над базой данных, вы сможете предотвратить эту проблему в будущем, utf8mb4 свою базу данных для использования utf8mb4 символов utf8mb4 . (Не просто используйте utf8 , либо он будет сбой по четырем байтам utf8, включая большинство emojis). Тогда вам будет гарантировано иметь действительный utf-8, который хранится и возвращается из вашей базы данных.

Сделайте столбец, который вы храните в BLOB . После загрузки данных выполните различные действия, такие как

  SELECT MAX(LENGTH(col)) FROM ... -- to see what the longest is in _bytes_. 

Скопируйте данные в другой столбец BLOB и сделайте

  ALTER TABLE t MODIFY col2 TEXT CHARACTER SET utf8 ... -- to see if it converts correctly 

Если это удастся, тогда сделайте

  SELECT MAX(CHAR_LENGTH(col2)) ... -- to see if the longest is more than 500 _characters_. 

После того, как вы попробовали несколько таких вещей, мы можем видеть, какое направление следует предпринять дальше.

Короче говоря, ваша настройка MySQL неверна в том, что она усекает символы UTF-8 в середине последовательности. Я бы дважды проверял, что MySQL действительно ожидает кодировку символов UTF-8 в сеансах и самих таблицах.


Я бы предложил переключиться на PostgreSQL (серьезно), чтобы избежать такой проблемы: не только PostgreSQL правильно понимает UTF-8 в конфигурациях по умолчанию, но также не будет усекать строку, чтобы вписаться в значение, выбирая вместо этого ошибку :

 psql (9.5.3, server 9.5.3) Type "help" for help. testdb=> create table foo(bar varchar(4)); CREATE TABLE testdb=> insert into foo values ('aaaaa'); ERROR: value too long for type character varying(4) 

Это также не похоже на Zen Python:

Явный лучше, чем неявный.

а также

Ошибки никогда не должны проходить молча.
Если явно не замолчать.
Перед лицом двусмысленности откажитесь от соблазна угадать.

  • pandas to_sql дает ошибку декодирования Unicode
  • Прочтите много файлов csv и запишите их в кодировку utf8 с помощью python
  • Ошибка открытия файла с помощью кодека utf-8 в python
  • Python: UnicodeDecodeError: кодек ascii не может декодировать байт 0xef в позиции 0: порядковый номер не в диапазоне (128)
  • Python, вывод кодировки в UTF-8
  • Unescape unicode-escapes, но не возвращает каретки и линейные фиды, в Python
  • Ошибка кодирования в Django на Heroku
  • Python zlib output, как восстановить из таблицы mysql utf-8?
  • Python - лучший язык программирования в мире.