Python 3 和 MySQL 连接器出现 Unicode 和不正确的参数数量错误

Unicode and incorrect number of arguments errors with Python 3 and MySQL connector

我正在尝试对 Python 中的 MySQL(MariaDB) 数据库执行一个简单的 SELECT 查询 3.

我遇到了非常奇怪的错误

        query = (
            'SELECT user_id, user_password_hash, user_password_salt '
            'FROM users '
            'WHERE user_username = "%s"'
        )

        print(f'Trying login, username {username}, password {password}')

        try:
            cursor = self.connection.cursor(prepared=True)
            cursor.execute(query, (username,))

            results = cursor.fetchone()

            print(results)
            ...

        except Error as e:
            print('Error in login query: ' + str(e))
            raise e

运行 此代码给我以下错误: Error in login query: 1210: Incorrect number of arguments executing prepared statement

我不明白 - 它需要一个参数,我已经给了它一个参数。 删除 execute() 中元组中的逗号并不能解决此问题。

现在,如果我从查询中删除引号,我会得到一个完全不同的错误:

        query = (
            'SELECT user_id, user_password_hash, user_password_salt '
            'FROM users '
            'WHERE user_username = %s'
        )
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x9b in position 0: invalid start byte

The above exception was the direct cause of the following exception:

SystemError: <class 'UnicodeDecodeError'> returned a result with an error set

table 使用的是 utf8mb4,所以这应该不是问题。

此外,MySQL 控制台中的 运行 SELECT * FROM users WHERE user_username="jeff" 工作正常。

这应该是一个非常简单的查询,但我完全不知道发生了什么 - 任何帮助将不胜感激。

编辑:在孤立的 Python 过程中进行实验时,我通过 运行 重现了这个问题:

import mysql.connector

conn = mysql.connector.connect(host="localhost",
                               database="lucidlab",
                               user="lucidlab",
                               password="lucidlab")

cur = conn.cursor()
cur.execute("SELECT * FROM users WHERE user_username='jeff'")

results = cur.fetchall() # ERROR
print(results)

这让我觉得可能是数据库编码问题?

编辑:我已经解决了这个问题。请看下面我的回答。

尝试使用双引号:

    query = ("SELECT user_id, user_password_hash, user_password_salt "
        "FROM users "
        "WHERE user_username = %s"
    )

或三重引语:

    query = ("""SELECT user_id, user_password_hash, user_password_salt 
        FROM users 
        WHERE user_username = %s"""
    )

query = """SELECT user_id, user_password_hash, user_password_salt FROM users WHERE user_username = %s"""

用这个就可以了..

我找到问题了。修复它需要查看架构,不幸的是我没有这样做 post - 经验教训。

我的架构包含以下内容:

CREATE TABLE users (
...
  user_password_hash BINARY(20) NOT NULL,
  user_password_salt BINARY(20) NOT NULL,
...
);

运行 任何类型SELECT * FROM users... 查询检索此二进制数据,Python 有用(!)立即将其转换为 UTF -8 string... 失败,因为盐是从 os.urandom().

产生的字节

我通过使用 passlib 库中的 sha256_crypt 并将我的编码哈希+盐组合存储为 CHAR(77) 来修复此问题。

感谢那些提供帮助的人 - 不幸的是,我对这个问题的思考过于狭隘,因此我的问题是这样表述的。