Python mysqlclient и данные на двух разных серверах - PullRequest
0 голосов
/ 03 октября 2019

На моей локальной машине (MacOS) у меня есть MariaDB 10.4, Python 3.7.4 и mysqlclient 1.4.4. На удаленном сервере (FreeBSD) у меня есть MySQL 5.2, Python 3.7.2 и mysqlclient 1.4.4.

База данных в кодировке utf8 на обеих машинах.

Мой скрипт использует запрос сCONCAT, например:

SELECT IF(agreements.date <> '0000-00-00', CONCAT(agreements.date, ' 00:00:00 +0300'), '').....

Почему на моем локальном компьютере класс значений в результирующем кортеже всегда равен STR , а на удаленном сервере - STR или BYTES и каждое значение столбца, в котором я использовал функцию CONCAT в mysql, начинается с b '...' и имеет класс BYTES . Я знаю, что могу декодировать байтовые значения (b.decode ()) и оставить другие значения str такими, как

data = cursor.fetchall()
l = [list(x) for x in data]
for d in l:
    for idx, vals in enumerate(d):
        if isinstance(vals, bytes):
            d[idx] = vals.decode()

, но почему это произошло - версия MySQL ??

Я вижу дваспособы: декодировать через Python, как я написал, или использовать функцию mysql CONVERT <column> USING utf8, как сказал @Joe McKenna. Но почему я не должен делать это на локальном компьютере, я не знаю :( Версии сервера MySQL разные, но конфигурация charset такая же.

Пример сценария:

#!/usr/local/bin/python3
# coding: utf8


import MySQLdb

connection = MySQLdb.Connection(
    user='root',
    passwd='password',
    db='billing',
    host='localhost',
    charset='utf8'
)

cursor = connection.cursor()


cursor.execute("SELECT '', CONCAT(birthdate, ' TEST!!!!!') from accounts")
for d in cursor.fetchall():
    print(d)

cursor.close()
connection.close()

Вывод:

('', b'1958-11-11 TEST!!!!!')
('', b'0000-00-00 TEST!!!!!')
('', b'0000-00-00 TEST!!!!!')
('', b'0000-00-00 TEST!!!!!')
('', b'0000-00-00 TEST!!!!!')
('', b'0000-00-00 TEST!!!!!')
('', b'0000-00-00 TEST!!!!!')
('', b'0000-00-00 TEST!!!!!')
('', b'1950-10-09 TEST!!!!!')

ОБНОВЛЕНИЕ:

Результат mysql> SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';

Локальный хост:

+--------------------------+--------------------+
| Variable_name            | Value              |
+--------------------------+--------------------+
| character_set_client     | utf8               |
| character_set_connection | utf8               |
| character_set_database   | utf8               |
| character_set_filesystem | binary             |
| character_set_results    | utf8               |
| character_set_server     | utf8mb4            |
| character_set_system     | utf8               |
| collation_connection     | utf8_general_ci    |
| collation_database       | utf8_general_ci    |
| collation_server         | utf8mb4_general_ci |
+--------------------------+--------------------+

Удаленный сервер:

+--------------------------+-----------------+
| Variable_name            | Value           |
+--------------------------+-----------------+
| character_set_client     | utf8            |
| character_set_connection | utf8            |
| character_set_database   | utf8            |
| character_set_filesystem | binary          |
| character_set_results    | utf8            |
| character_set_server     | utf8            |
| character_set_system     | utf8            |
| collation_connection     | utf8_general_ci |
| collation_database       | utf8_general_ci |
| collation_server         | utf8_general_ci |
+--------------------------+-----------------+

1 Ответ

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

Встроить тип вывода во все запросы с ключевым словом 'convert', как в этом сообщении:


Преобразовать выходные данные MySQL-запроса в utf8


SELECT column1, CONVERT (column2 USING utf8) FROM my_table WHERE my_condition;


Или вы можете использовать команду 'alter', чтобы изменить каждый столбец в БД на нужный вам тип данных:


https://dba.stackexchange.com/questions/33365/tell-mysql-to-start-using-utf-8-encoding-without-convert-toing-it


...