Подтвердить что ты не робот

Результат SQLAlchemy для столбца UTF-8 имеет тип 'str', почему?

У меня есть SQL-запрос, который я выполняю с помощью механизма SQLAlchemy:

result = engine.execute('SELECT utf_8_field FROM table')

База данных - это MySQL, а тип столбца - TEXT с кодировкой UTF-8. Тип возвращаемого utf_8_field - "str", даже если я устанавливаю параметр convert_unicode = True при создании движка. Теперь случается так, что если в моей строке есть символ "é" (который не находится в 7-разрядном ASCII, но находится в расширенном наборе ASCII), я получаю UnicodeDecodeError при попытке выполнить это:

utf_8_field.encode("utf-8")

Точная ошибка:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 1: ordinal not in range(128)

При изучении этого я обнаружил, что str.encode не поддерживает расширенный набор символов ASCII! Я нахожу это действительно странным, но это еще один вопрос.

Я не понимаю, почему SQLAlchemy не дает мне строку unicode. Раньше я использовал DB-API, и он работал нормально. У меня также нет табличных объектов SQLAlchemy для моих таблиц, поэтому я использую команду execute.

Любая идея?

4b9b3361

Ответ 1

Если вы хотите, чтобы данные были преобразованы автоматически, вы должны указать кодировку при создании движка:

create_engine('mysql+mysqldb:///mydb?charset=utf8')

Настройка use_unicode сама по себе не укажет sqlalchemy, какую кодировку использовать.

Ответ 2

Чтобы преобразовать из UTF-8 bytestring в объект unicode, вам необходимо декодировать:

utf_8_field.decode('utf8')

Кроме того, при выполнении raw SELECT через .execute SQLAlchemy не имеет метаданных для разработки того, что ваш запрос возвращает данные utf-8, поэтому он не преобразует эту информацию в unicode для вас.

Другими словами, convert_unicode работает только в том случае, если вы используете SQL-выражение SQLAlchemy API или функциональность ORM.

EDIT: как указано, ваши данные даже не кодируются кодировкой UTF-8; 0xe9 в UTF-8 будет указывать символ между \u9000 и \u9fff, которые являются унифицированными идеологами CJK, пока вы сказали, что это символ латинского-1, код UTF-8 которого начинается с 0xc3. Это, вероятно, ISO-8859-1 (латинский-1) или похожий:

>>> u'é'.encode('ISO-8859-1')
'\xe9'

Затем следует сказать, что SQLAlchemy соединяется с другим набором символов, используя параметр charset=utf8, как указано @mata.