Проблема кодировки символов при использовании Python3 / mysqlclient для получения данных, закодированных в латинице 1 - PullRequest
3 голосов
/ 15 октября 2019

Я сталкиваюсь с проблемой кодировки символов при извлечении данных из более старой базы данных, которая использует кодировку latin1. Проблема возникает, когда я пытаюсь извлечь из базы данных символы, попадающие в диапазон от \x80 до \x9f, который отличается от MySQL latin1 (он же windows-1252 в Python) и официального latin1 (ISO-8859-1).

Это стек, который я использую:

  • Сервер баз данных MySQL версии 5.1 с кодированием latin1 на уровне столбцов и сопоставлением latin1-swedish-ci на уровне таблиц.
  • Django версии 2.2 с использованием Python3 и mysqlclient версии 1.4.4.

В качестве примера я пытаюсь извлечь слово «нет» из базы данных, где находится апострофзакодировано как \x92.

Если я не передам кодировку соединению mysqlclient через настройки Django, я получаю сообщение об ошибке «Кодек utf-8 не может декодировать байт 0x92 в позиции 5: недействительноначальный байт ".

Если я передаю latin1 в качестве кодека для соединения, ошибки не возникает, но слово отображается на странице как" Is t ", с пробелом, где должен быть апостроф.

Когда я открываю отдельную сессию оболочки Python и пытаюсь установить соединение из командной строки python, в результате получается «Isn \ x92t».

>>> import MySQLdb
>>> conex = MySQLdb.connect(host=<host>,db=<db>, user=<user>, passwd=<passwd>, charset="latin1")
>>> cursor = conex.cursor()
>>> cursor.execute("select <field> from <table> where id=<id>")
1L
>>> cursor.fetchall()
((u'Isn\x92t',),)

Кажется, что нет никакой разницы, еслиЯ включаю кодировку или нет при совершении звонкаом командной строки. Таким образом, эта строка подключения

>>> conex = MySQLdb.connect(host=<host>,db=<db>, user=<user>, passwd=<passwd>, charset="latin1")

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

>>> conex = MySQLdb.connect(host=<host>,db=<db>, user=<user>, passwd=<passwd>)

имеют одинаковый результат.

Есть ли способ установить параметры для строки подключения mysql, которыебудет правильно обрабатывать коды windows-1252? Буду признателен за любую помощь.

========= Редактировать с дополнительной информацией =========

Спасибо за ваш ответ Рик Джеймс. Исходный текстовый фрагмент исчез, но я нашел еще один похожий фрагмент, на котором он не работает: женский.

Вот выбор HEX:

mysql> SELECT title, HEX(title) from <table> where id = <id>
| title | HEX(title)
| Women?s | 576F6D656E9273

Я не уверен, что чувствую себя комфортно, помещаяВся инструкция по созданию таблицы в Интернете, но вот что я понял, это важные биты SHOW CREATE TABLE. Дайте мне знать, если вы ищете что-то еще.

CREATE TABLE `tbl` (
  `title` varchar(255) DEFAULT NULL,
) ENGINE=MyISAM AUTO_INCREMENT=9460 DEFAULT CHARSET=latin1 

И, наконец, результаты SHOW VARIABLES LIKE 'char%';:

+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | latin1                     |
| character_set_connection | latin1                     |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | latin1                     |
| character_set_server     | latin1                     |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |

Изменение кодировки в файле настроек базы данных Django на utf8mb4В результате возникла та же ошибка Unicode, что и при установке utf8.

'OPTIONS': {
  'charset': 'utf8mb4',
  'use_unicode': True,
}

Я все еще немного озадачен тем, почему прямой запрос с использованием автономной среды Python с mysqlclient не будет работать. Это, по крайней мере, исключило бы любую проблему с Джанго из уравнения.

1 Ответ

1 голос
/ 15 октября 2019

Эти кодировки cp1250, cp1251, cp1256, cp1257, geostd8, latin1 рассматривают x92 как .

В настройке Django должна указываться кодировка символов, которую вы хотите использовать в клиенте. Это не зависит от того, что находится в базе данных. Таким образом, возникает вопрос: «Где что-то неправильно настроено?»

Введет u неправильно, так как 92 не является допустимым UTF-8.

  • кодировка latin1 на уровне столбца -штраф
  • 0x92 в данных - подтвердите, выполнив SELECT col, HEX(col) ...;Isn't должен сказать 49736E9274.
  • Исходный код Python должен начинаться с # -*- coding: utf-8 -*-, если вы хотите использовать UTF-8 в клиенте.
  • Django нуждается в этом для utf8mb4в клиенте:

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            ...
            'OPTIONS': {
                        'charset': 'utf8mb4',
                        'use_unicode': True, },
        },
    }
    

Для получения дополнительной помощи, пожалуйста, предоставьте

SHOW CREATE TABLE ...;
SHOW VARIABLES LIKE 'char%';
the SELECT HEX mentioned above

Дополнительные примечания (после того, как Вопрос был значительно расширен)

Woman?s - см. Вопросительный знак в Проблема с символами UTF-8;я вижу не то, что сохранил - Вероятно, это происходит из-за того, что соединение (char%) является latin1, а клиент (DJango) говорит utf8mb4. 3 параметра char% определяют, что клиент использует для кодирования;настройка DJango противоречит этому. Поменяйте одно или другое. Столбец таблицы не должен соответствовать им;данные будут преобразованы по мере необходимости. То есть, 92 в столбце latin1 в порядке, даже с символьным_клиентом / подключением / результатами = utf8mb4.

Для этого вопроса utf8 и utf8mb4 будут действовать одинаково.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...