【Python奇遇记】Pymysql连接MySQL报TypeError

Python连接mysql报TypeError

问题: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读取结果很奇怪

Pymysql读取结果显示b'\x01'或者b'\x00'

原因: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}]

你可能感兴趣的:(mysql,数据库)