【问题标题】:UnboundLocalError: local variable 'cursor' referenced before assignmentUnboundLocalError:分配前引用的局部变量“光标”
【发布时间】:2015-12-06 06:05:26
【问题描述】:

所以我是一个新手,但正在使用flask/MYSQL 中的注册系统表单

我收到此错误(UnboundLocalError: local variable 'cursor' referenced before assignment)

在玩了几个小时的代码和研究之后,我需要你的帮助。

这是我的文件,如果还有什么需要分享的,请告诉我。 谢谢

from flask import Flask, render_template, json, request
from flask.ext.mysqldb import MySQL
from werkzeug import generate_password_hash, check_password_hash

app = Flask(__name__)
mysql = MySQL()


app.config['MYSQL_DATABASE_USER'] = 'x'
app.config['MYSQL_DATABASE_PASSWORD'] = 'x'
app.config['MYSQL_DATABASE_DB'] = 'x'
app.config['MYSQL_DATABASE_HOST'] = 'x'
mysql.init_app(app)

@app.route('/')
def main():
    return render_template('index.html')

@app.route('/login')
def login():
    return render_template('login.html')

@app.route('/showSignUp')
def showSignUp():
    return render_template('signup.html')


@app.route('/signUp',methods=['POST','GET'])
def signUp():
    try:
        _name = request.form['inputName']
        _email = request.form['inputEmail']
        _password = request.form['inputPassword']

        # validate the received values
        if _name and _email and _password:

            # All Good, let's call the MySQL

            conn = mysql.connect()
            cursor = conn.cursor()
            _hashed_password = generate_password_hash(_password)
            cursor.callproc('sp_createUser',(_name,_email,_hashed_password))
            data = cursor.fetchall()

            if len(data) is 0:
                conn.commit()
                return json.dumps({'message':'User created successfully !'})
            else:
                return json.dumps({'error':str(data[0])})
        else:
            return json.dumps({'html':'<span>Enter the required fields</span>'})

    except Exception as e:
        return json.dumps({'error':str(e)})
    finally:
        cursor.close()
    conn.close()

if __name__ == '__main__':
    app.run()

【问题讨论】:

    标签: python mysql flask sqlalchemy mysql-python


    【解决方案1】:

    您只在 if 块中定义 conncursor 检查表单值。如果未输入块,则它们未定义,但您仍然尝试引用它们以关闭它们。如果你已经定义了它们,你应该只在两者上调用close。要么将 conn =cursor = 移到 if 块之前,要么将 close 调用移到块内。

    但是,更大的问题是您对如何使用 Flask-MySQLdb 有误解/过于复杂。它会在请求完成时自动创建连接并关闭它,这也会关闭游标。只需使用docs 中所述的扩展名即可。

    ...
    cur = mysql.connection.cursor()
    cur.callproc('sp_createUser', (name, email, hashed_password))
    data = cur.fetchall()
    ...
    

    【讨论】:

      【解决方案2】:

      我个人建议使用上下文管理器来处理光标和连接的打开和关闭。您可以相当简单地实现这一点,并且它更干净,更易于调试。这也将消除尝试关闭连接或游标之前在您的巨型 try except 块中打开它的问题。

      from contextlib import closing
      
      # do a bunch of stuff prior to opening connection
      with closing(mysql.connect()) as conn:
          with closing(conn.cursor()) as cursor:
              # do a bunch of stuff and don't worry about running .close()
      

      您可以查看closing here 的文档。

      使用closing 会将您的代码更改为类似这样。虽然它可以使用更多的重构,但这是代码审查网站的问题。

      from flask import Flask, render_template, json, request
      from flask.ext.mysqldb import MySQL
      from werkzeug import generate_password_hash, check_password_hash
      from contextlib import closing
      
      app = Flask(__name__)
      mysql = MySQL()
      
      
      app.config['MYSQL_DATABASE_USER'] = 'x'
      app.config['MYSQL_DATABASE_PASSWORD'] = 'x'
      app.config['MYSQL_DATABASE_DB'] = 'x'
      app.config['MYSQL_DATABASE_HOST'] = 'x'
      mysql.init_app(app)
      
      @app.route('/')
      def main():
          return render_template('index.html')
      
      @app.route('/login')
      def login():
          return render_template('login.html')
      
      @app.route('/showSignUp')
      def showSignUp():
          return render_template('signup.html')
      
      
      @app.route('/signUp',methods=['POST','GET'])
      def signUp():
          try:
              _name = request.form['inputName']
              _email = request.form['inputEmail']
              _password = request.form['inputPassword']
      
              # validate the received values
              if _name and _email and _password:
      
                  # All Good, let's call the MySQL
      
                  with closing(mysql.connect()) as conn:
                      with closing(conn.cursor()) as cursor:
                          _hashed_password = generate_password_hash(_password)
                          cursor.callproc('sp_createUser',(_name,_email,_hashed_password))
                          data = cursor.fetchall()
      
                          if len(data) is 0:
                              conn.commit()
                              return json.dumps({'message':'User created successfully !'})
                          else:
                              return json.dumps({'error':str(data[0])})
              else:
                  return json.dumps({'html':'<span>Enter the required fields</span>'})
      
          except Exception as e:
              return json.dumps({'error':str(e)})
      
      if __name__ == '__main__':
          app.run()
      

      【讨论】:

      • 所以我删除了我的 finally 代码,直到 if name 并将其替换为您的 cmets 之间的代码并导入上下文库?
      • 是的,删除 finally 语句并导入该库并将 opens 更改为 with 语句,您应该会很好。
      • 啊,我明白了。我以前从未使用过烧瓶,但我熟悉纯 python 中的手动数据库连接。
      • @JasonMartinez,切换到 django。 ;) djangoproject.com喜剧+1
      • @electrometro 我想了一会儿,但我花了很多时间在视频和研究如何用 Python 和烧瓶做事,我拒绝放弃。最终虽然我可能会。
      猜你喜欢
      • 1970-01-01
      • 2017-08-10
      • 2020-01-16
      • 2019-12-05
      • 2017-09-19
      • 2020-09-26
      • 2022-01-02
      • 2019-03-22
      • 2019-01-24
      相关资源
      最近更新 更多