问题:Python连接mysql时报TypeError: object supporting the buffer API required
# 数据库配置文件config_mysql.yaml
host: 192.168.1.1
port: 3306
user: test001
passwd: 123456
db: test_db
charset: utf8
import pymysql
import yaml
# 读取yaml配置文件
with open(file="config_mysql.yaml", mode="r", encoding="utf-8") as f:
data = yaml.safe_load(f.read())
# 建立数据库连接
conn = pymysql.connect(**data)
# 定义游标
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# sql语句
sql = "select id,is_del,status from member order by 1 desc limit 3;"
# 执行sql语句
cursor.execute(sql)
# 获取执行结果
results = cursor.fetchall()
print(results)
# 关闭数据库连接
conn.close()
# 运行结果
Traceback (most recent call last):
File "D:\Python Projects\DataQuery\test.py", line 15, in
conn = pymysql.connect(host=host, user=user, passwd=passwd, port=port, db=db, charset=charset)
File "D:\Python Projects\DataQuery\venv\lib\site-packages\pymysql\connections.py", line 353, in __init__
self.connect()
File "D:\Python Projects\DataQuery\venv\lib\site-packages\pymysql\connections.py", line 633, in connect
self._request_authentication()
File "D:\Python Projects\DataQuery\venv\lib\site-packages\pymysql\connections.py", line 869, in _request_authentication
authresp = _auth.scramble_caching_sha2(self.password, self.salt)
File "D:\Python Projects\DataQuery\venv\lib\site-packages\pymysql\_auth.py", line 198, in scramble_caching_sha2
p1 = hashlib.sha256(password).digest()
TypeError: object supporting the buffer API required
原因:传的密码是一串数字123456,python在读配置文件过程中默认把123456转成了整型
解决:将配置文件config_mysql.yaml中密码passwd从123456改为'123456'
# 数据库配置文件config_mysql.yaml
host: 192.168.1.1
port: 3306
user: test001
passwd: '123456'
db: test_db
charset: utf8
# 修改后运行结果
[{'id': 775, 'is_del': b'\x00', 'status': b'\x01'}, {'id': 774, 'is_del': b'\x00', 'status': b'\x01'}, {'id': 773, 'is_del': b'\x00', 'status': b'\x01'}]
【但是】这里又出现了一个新的问题,is_del和status读取结果很奇怪
原因:MySQL表中bit类型的数据(相当于Python中的True或者False),Python读取后并不会自动处理
解决:使用ord函数对结果进行转换
同时对上面的代码进行了优化和封装,此时is_del和status读取结果正常,为0或者1
import traceback
import pymysql
import yaml
class TestMysql:
def __init__(self):
dbinfo = self.yaml_read("config_mysql.yaml") # 读取数据库配置
self.conn = pymysql.connect(**dbinfo) # 建立数据库连接
self.cursor = self.conn.cursor(cursor=pymysql.cursors.DictCursor) # 定义游标
def execute(self, sql):
try:
self.cursor.execute(sql) # 执行sql语句
data = self.cursor.fetchall() # 获取执行结果
self.data_handle(data) # 转换bit类型
return data
except Exception as err:
self.conn.rollback() # 执行异常时回滚
info = f"出了点小问题!\n{repr(err)}\n{traceback.format_exc()}"
return info
finally:
self.conn.close() # 关闭数据库连接
@staticmethod
def yaml_read(file):
"""读取yaml配置文件"""
with open(file=file, mode="r", encoding="utf-8") as f:
data = yaml.safe_load(f.read())
return data
@staticmethod
def data_handle(data):
"""遍历数据库读取结果,转换bit类型"""
for i, val in enumerate(data):
for index, key in enumerate(val):
if isinstance(val[key], bytes): # 若值为bit类型,转换为0或者1
val[key] = ord(val[key])
if __name__ == "__main__":
result = TestMysql().execute("select id,is_del,status from member order by 1 desc limit 3;")
print(result)
# 运行结果
[{'id': 775, 'is_del': 0, 'status': 1}, {'id': 774, 'is_del': 0, 'status': 1}, {'id': 773, 'is_del': 0, 'status': 1}]