Правильное получение BLOB-объектов из базы данных MySQL с помощью MySQL-коннектора в Python - PullRequest
0 голосов
/ 11 октября 2018

При выполнении следующего кода:

import mysql.connector
connection = mysql.connector.connect(...) # connection params here
cursor = connection.cursor()
cursor.execute('create table test_table(value blob)')
cursor.execute('insert into test_table values (_binary %s)', (np.random.sample(10000).astype('float').tobytes(),))
cursor.execute('select * from test_table')
cursor.fetchall()

я получаю следующую ошибку:

UnicodeDecodeError: кодек «utf-8» не может декодировать байт 0xf7 в позиции 1: недопустимый начальный байт

(... а затем трассировка стека, которую я не считаю полезной здесь)

Кажется, что соединитель mysql преобразует мой двоичный объект в строку (ине в состоянии сделать это).Как я могу получить эти данные в байтах без преобразования?

Ответы [ 3 ]

0 голосов
/ 25 ноября 2018

Мы столкнулись с той же проблемой, что BLOB-объекты были ошибочно считаны как строки UTF-8 с MySQL 8.0.13, mysql-connector-python 8.0.13 и sqlalchemy 1.2.14.

В чем дело?для нас была включена опция use_pure MySQL Connector .Значение по умолчанию use_pure изменилось в 8.0.11 с новым значением по умолчанию - использование расширения C.Таким образом, мы вернули опцию:

create_engine(uri, connect_args={'use_pure': True}, ...)

Детали нашей ошибки и трассировки стека:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x9c in position 1: invalid start byte
The above exception was the direct cause of the following exception:

Traceback (most recent call last):
    ....
    File "/usr/local/lib/python3.6/site-packages/mysql/connector/cursor_cext.py", line 272, in execute
        self._handle_result(result)
    File "/usr/local/lib/python3.6/site-packages/mysql/connector/cursor_cext.py", line 163, in _handle_result
        self._handle_resultset()
    File "/usr/local/lib/python3.6/site-packages/mysql/connector/cursor_cext.py", line 651, in _handle_resultset
        self._rows = self._cnx.get_rows()[0]
    File "/usr/local/lib/python3.6/site-packages/mysql/connector/connection_cext.py", line 273, in get_rows
        row = self._cmysql.fetch_row()
    SystemError: <built-in method fetch_row of _mysql_connector.MySQL object at 0x5627dcfdf9f0> returned a result with an error set
0 голосов
/ 13 марта 2019

Я воспроизвел вышеуказанную ошибку:

Traceback (most recent call last):
File "demo.py", line 16, in <module>
    cursor.execute(query, ())
return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode byte '0xff ... ' 
in position 0: invalid start byte

Использование версий:

$  python --version
Python 2.7.10

>>> mysql.connector.__version__
'8.0.15'

С кодом Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
import mysql.connector
conn = mysql.connector.connect(
      user='asdf', 
      password='asdf',
      host='1.2.3.4',
      database='the_db',
      connect_timeout=10)

cursor = conn.cursor(buffered=True)                     #error is raised here
try:
    query = ("SELECT data_blob FROM blog.cmd_table")
    cursor.execute(query, ())                         
except mysql.connector.Error as err:                    #error is caught here
    #error is caught here, and printed:
    print(err)                                          #printed thustly

Использование Python-переменной «raw-байтовый двоичный файл», заполненной Python open( следующим образом:

def read_file_as_blob(filename):
    #r stands for read
    #b stands for binary
    with open(filename, 'rb') as f:
        data = f.read()
    return data

Таким образом, проблема находится где-то между преобразованием кодирования данных в файле-> кодирование данных для BLOB-объекта mysql -> и как mysql поднимает этот BLOB-объект и преобразует его обратно в utf-8.

Два решения:

Решение 1 - этоточно так же, как сказал AHalvar, установите параметр use_pure=True и передайте значение mysql.connector.connect( ... ).Тогда загадочным образом это просто работает.Но хорошие программисты заметят, что задержка в таинственном заклинании - это неприятный запах кода.Исправления по броуновскому движению влекут за собой технические долги.

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

Приятным решением для меня было принудительное использование кодировки utf-8 на более ранних этапах процесса.Повсеместное применение UTF-8.

data.encode('UTF-8')

Юникодная куча poo отражает мое мнение о такой няне кодирования символов между различными устройствами в разных операционных системах и схемах кодирования.

0 голосов
/ 25 октября 2018

По-видимому, это известная проблема с модулем Python 'mysql'.Попробуйте вместо этого использовать 'pymysql'.

...