【问题标题】:drop_all() freezes in Flask with SQLAlchemy使用 SQLAlchemy 在 Flask 中冻结 drop_all()
【发布时间】:2014-06-18 15:43:24
【问题描述】:

我正在为 Flask 应用程序编写测试用例。

我有一个 setUp 方法,它在重新创建它们之前删除数据库中的表。 它看起来像这样:

def setUp(self):
    # other stuff...
    myapp.db.drop_all()
    myapp.db.create_all()
    # db creation...

这适用于第一个测试,但在运行第二个测试之前它会冻结在drop_all

编辑: 中断进程时的堆栈跟踪是这样的

  File "populate.py", line 70, in create_test_db
    print (myapp.db.drop_all())
  File ".../flask_sqlalchemy/__init__.py", line 864, in drop_all
    self._execute_for_all_tables(app, bind, 'drop_all')
  File ".../flask_sqlalchemy/__init__.py", line 848, in _execute_for_all_tables
    op(bind=self.get_engine(app, bind), tables=tables)
  File ".../sqlalchemy/sql/schema.py", line 3335, in drop_all
  ....
  File "/Library/Python/2.7/site-packages/MySQLdb/cursors.py", line 190, in execute
    r = self._query(query)

有人知道如何解决这个问题吗?

【问题讨论】:

    标签: python flask


    【解决方案1】:

    Oki,可能还有其他解决方案,但现在,在搜索互联网后,我发现如果我在代码前加上 myapp.db.session.commit(),问题就会消失。我猜,某处事务正在等待提交。

    def setUp(self):
        # other stuff...
        myapp.db.session.commit()   #<--- solution!
        myapp.db.drop_all()
        myapp.db.create_all()
        # db creation...
    

    【讨论】:

    • postgres 也有同样的问题。
    • 包含更多关于数据库流中实际出了什么问题的上下文会很棒。这里的答案只是告诉人们提交是一个“解决方案”,但没有关于所述问题的详细信息。
    【解决方案2】:

    只需关闭应用中的所有会话,然后调用 drop_all

        def __init__(self, conn_str):
            self.engine = create_engine(conn_str)
            self.session_factory = sessionmaker(engine)
            
        def drop_all(self):
            self.session_factory.close_all() # <- don't forget to close
            Base.metadata.drop_all(self._engine)
    

    有关 SQLAlchemy 中的会话的更多信息 http://docs.sqlalchemy.org/en/latest/orm/session_api.html?highlight=close_all

    【讨论】:

    • 你是一个多么了不起、不可思议、美妙、可爱、美丽的人。非常感谢。
    • 在 Pyramid 中与 SQLAlchemy 有同样的问题。谢谢!
    • 请注意,对于 SQLAlchemy 1.3,“Session.close_all() 方法已弃用,将在未来的版本中删除。”新命令是:from sqlalchemy.orm.session import close_all_sessions 然后close_all_sessions()
    【解决方案3】:

    我是一名 Flask 开发人员,使用 flask_sqlalchemy 和 pytest 测试我的应用服务器,当我运行语句 db.drop_all() 时遇到类似的情况,控制台显示我的一个表被锁定。

    我使用db.session.remove()在运行 db.drop_all() 之前删除会话。

    【讨论】:

      【解决方案4】:

      我遇到了同样的问题,在我的情况下,我有 2 个不同的会话对同一个表进行查询。我的解决方案是在两个地方都使用一个 scoped_session。

      我在不同的模块中创建它,所以循环依赖没有问题,如下所示:

      db.py:

      from flask.ext.sqlalchemy import SQLAlchemy
      db = SQLAlchemy()
      

      models.py:

      from .db import db
      class User(db.Model):
          id = db.Column(db.Integer, primary_key=True)
          username = db.Column(db.String(80), unique=True)
      

      app.py:

      from flask import Flask
      from .db import db
      app = Flask(__name__)
      db.init_app(app)
      

      在您的所有代码中仅使用db.session 将保证您在同一个会话中。在测试中,确保在 tearDown 执行回滚。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-30
        • 2021-10-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多