Flask中使用SQLAlchemy时drop_all()冻结
我正在为一个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)
有没有人知道怎么解决这个问题?
4 个回答
1
我之前也遇到过同样的问题。在我的情况中,有两个不同的会话同时对同一张表进行查询。我的解决办法是为这两个地方使用一个共享的会话。
我在一个不同的模块中创建了这个会话,这样就避免了循环依赖的问题,代码如下:
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
,这样可以确保你在同一个会话里。在测试时,记得在清理时执行回滚操作。
5
我是一个Flask开发者,正在使用flask_sqlalchemy和pytest来测试我的应用服务器。当我运行命令 db.drop_all()
时,控制台显示我的一个表被锁住了。
在运行 db.drop_all()
之前,我使用 db.session.remove()
来清除会话。
30
只需要在你的应用里关闭所有的会话,然后再调用 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
45
好的,可能还有其他解决办法,但目前为止,我在网上查找后发现,如果我在代码前面加上一个 myapp.db.session.commit()
,问题就解决了。我想,可能是某个地方的事务在等待提交。
def setUp(self):
# other stuff...
myapp.db.session.commit() #<--- solution!
myapp.db.drop_all()
myapp.db.create_all()
# db creation...