使用 python 中的 mysql 连接器从 mysql 数据库正确获取 blob



执行以下代码时:

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 连接器将我的 blob 转换为字符串(并且未能这样做(。如何在不进行任何转换的情况下以字节形式获取此数据?

我们遇到了同样的问题,即 BLOB 被错误地读回 MySQL 8.0.13、mysql-connector-python 8.0.13 和 sqlalchemy 1.2.14 的 UTF-8 字符串。

对我们来说,诀窍是启用MySQL连接器的use_pure选项。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

我重现了上面的错误:

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'

使用蟒蛇代码

#!/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

使用由pythonopen(填充的python变量"原始字节二进制文件",如下所示:

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

因此,问题介于文件中数据的编码转换 ->mysql blob 的数据编码 -> 以及 mysql 如何提升该 blob 并将其转换回 utf-8 之间。

两种解决方案:

解决方案 1正如 AHalvar 所说,设置use_pure=True参数并传递给mysql.connector.connect( ... ). 然后神秘地它只是工作。 但是优秀的程序员会注意到,听从神秘的咒语是一种糟糕的代码气味。 布朗运动的修复会产生技术债务。

解决方案 2是尽早并经常对数据进行编码,并防止双重重新编码和双重数据解码,这是这些问题的根源。 尽快将其锁定为通用编码格式。

对我来说,令人满意的解决方案是在该过程的早期强制使用 utf-8 编码。 在任何地方强制使用 UTF-8。

data.encode('UTF-8')

一堆 unicode poo 代表了我对不同操作系统和编码方案上各种设备之间的字符编码这种婴儿化的看法。

显然,这是Python'mysql'模块的一个已知问题。尝试使用"pymysql"。

另一种方法是在连接初始化时使用raw=True参数:

connection = mysql.connector.connect(
host="localhost",
user="user",
password="password",
database="database",
raw=True
)

最新更新