pymysql.err.Error: Already closed

pymysql.err.Error: Already closed

我正在尝试创建一个登录功能。但它只适用于那些。例如,当我输入错误的用户 ID 和密码时,我得到了正确的错误提示 "Could't login" 在取消该消息并提供正确的用户 ID 和密码后,我得到 "pymysql.err.Error: Already closed" 以下是示例代码。

import pymysql

# Connect to the database
connection = pymysql.connect(host='localhost',
                             user='root',
                             password='',
                             db='python_code',
                             charset='utf8mb4',
                             cursorclass=pymysql.cursors.DictCursor)
class LoginModel:
    def check_user(self, data):

        try:
            with connection.cursor() as cursor:
                # Read a single record
                sql = "SELECT `username` FROM `users` WHERE `username`=%s"
                cursor.execute(sql, (data.username))
                user = cursor.fetchone()
                print(user)

            if user:
                if (user, data.password):
                    return user
                else:
                    return False
            else:
                return False

        finally:
            connection.close()

这是罪魁祸首代码:

finally:
    connection.close()

根据文档: "A finally clause is always executed before leaving the try statement, whether an exception has occurred or not" 来自:https://docs.python.org/2/tutorial/errors.html

你没有描述你希望看到的替代行为而不是这个,但我的回答解决了你问题的症结所在。

您创建连接的次数(一次)和关闭连接的次数(每次登录尝试一次)不匹配。

一个解决方法是移动您的:

connection = pymysql.connect(host='localhost',
                             user='root',
                             password='',
                             db='python_code',
                             charset='utf8mb4',
                             cursorclass=pymysql.cursors.DictCursor)

进入你的def check__user()。它会起作用,因为您会在每次调用时创建和关闭连接(正如其他人指出的那样,finally 子句总是被执行。)

这不是一个很好的设计,因为获取数据库连接往往相对昂贵。因此,最好在方法的 外部 保持连接创建....这意味着您必须在方法中删除 connection.close()

我认为您混淆了 connection.close()cursor.close()。你想做后者,而不是前者。在您的示例中,您不必显式关闭光标,因为 with connection.cursor() as cursor: 行会自动关闭光标。

finally 更改为 except,或完全删除 try 块。

有同样的问题。带有 psycopg2 驱动程序的 Postgres 需要“Finally 子句,如果与上下文管理器(with 子句)一起使用,它会关闭游标而不是连接。这同样不适用于 Pymysql。