首页 > 解决方案 > Python 中 Flask Web App 中的错误:pymysql.err.ProgrammingError: Cursor closed

问题描述

我似乎无法弄清楚我在烧瓶 Web 应用程序中收到“pymysql.err.ProgrammingError: Cursor closed”的错误。我确定我犯了一个小错误,但是关于这个错误的文档并不多。错误发生在“cursor.execute(query, email)”行。以下是我的代码:

from flask import Flask, render_template, request
import pymysql.cursors
import os

app = Flask(__name__)
IMAGES_DIR = os.path.join(os.getcwd(), "images")

conn = pymysql.connect(host='localhost',
                       port=8889,
                       user='LandingPage',
                       password='t9ybKLtVaS6qLQ7g',
                       db='LandingPage',
                       charset='utf8mb4',
                       cursorclass=pymysql.cursors.DictCursor)

@app.route('/', methods=['GET', 'POST'])
@app.route('/home', methods=['GET', 'POST'])
def home():
    if request.form:
        name = request.form['name']
        email = request.form['email']
        phone_number = request.form['phone number']

        with conn.cursor() as cursor:
            query = 'SELECT * FROM LandingPage WHERE email = %s'
            cursor.execute(query, email)
            data = cursor.fetchone()
            conn.commit()
        error = None
        if data:
            error = "A person with this email already exists in the database"
            return render_template('home.html', error=error)
        else:
            ins = "INSERT INTO LandingPage (name, email, phone number) VALUES (%s, %s, %s)"
            cursor.execute(ins, (name, email, phone_number))
            conn.commit()
            cursor.close()
            return render_template('home.html')
    return render_template('home.html')


if __name__ == "__main__":
    app.run('127.0.0.1', 4999, debug=True)

标签: pythondatabaseflaskweb-applications

解决方案


您看到的错误是在对象已关闭后尝试使用它的结果。大多数使用with关键字的对象都是为了控制对某些底层资源的访问。在这种情况下,它是数据库连接的游标。当您使用with关键字时,Python 将在执行内部代码块之前执行特定方法,并在该代码块完成时执行特定方法。这允许代码使用with关键字来控制诸如打开和关闭文件之类的事情。当您的代码退出该with块时,它会调用close()游标对象的方法,从而终止与数据库的数据连接。在那之后,您继续使用光标对象,因此它会给您该错误。

为了解决这个问题,每个涉及光标的交互都应该缩进到用with.

见下文:

@app.route('/', methods=['GET', 'POST'])
@app.route('/home', methods=['GET', 'POST'])
def home():
    if request.form:
        name = request.form['name']
        email = request.form['email']
        phone_number = request.form['phone number']

        with conn.cursor() as cursor:
            query = 'SELECT * FROM LandingPage WHERE email = %s'
            cursor.execute(query, email)
            data = cursor.fetchone()
            conn.commit()
            error = None # new indentation starts at this line
            if data:
                error = "A person with this email already exists in the database"
                return render_template('home.html', error=error)
            else:
                ins = "INSERT INTO LandingPage (name, email, phone number) VALUES (%s, %s, %s)"
                cursor.execute(ins, (name, email, phone_number))

        conn.commit()
        # cursor.close() # this line is redundant
        return render_template('home.html')
    return render_template('home.html')

推荐阅读