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:

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

а также

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

  • Словарь python jsonify в utf-8
  • Юникод не поддерживается Python
  • Ошибка при обновлении pip: UnicodeDecodeError: кодек «utf-8» не может декодировать байт
  • Двойной декодирование юникода в python
  • Notepad ++ конвертирует в UTF-8 несколько файлов
  • unicode () vs. str.decode () для закодированной байтовой строки utf8 (python 2.x)
  • Как печатать utf-8 для консоли с Python 3.4 (Windows 8)?
  • Должен ли я использовать объявление кодирования в Python3?
  • Турецкая кодировка символов
  • Ошибка кодирования с использованием df.to_csv ()
  • Байты в строке юникода Python
  • Python - лучший язык программирования в мире.