【发布时间】:2017-01-10 23:06:09
【问题描述】:
我有一个使用Flask RESTful 和Flask SQLAlchemy 的python 应用程序。我正在编写的 API 的一部分具有分离 Timer 对象的副作用。当Timer 过期时,它会执行一些数据库查询。我看到一个问题,其中应该更新数据库中的行(sqlite 后端)的代码实际上没有发出任何 UPDATE 语句。我已经通过打开SQLALCHEMY_ECHO 标志来记录SQL 语句来验证这一点。代码是否有效似乎是随机的。大约有一半的时间它没有发出UPDATE 声明。请参阅下面的完整示例。
我的猜测是 SQLAlchemy Flask 在从工作线程调用时无法正常工作。我认为 Flask SQLAlchemy 的部分重点是根据 API 请求为您管理 SQLAlchemy 会话。显然,由于Timer 过期时没有 API 请求进行,我可以看到可能无法正常工作的地方。
为了测试这个,我继续使用python的sqlite3 interface写了一个简单的数据访问层,它似乎解决了这个问题。
不过,我真的不想重写一堆数据访问代码。在这种情况下,有没有办法让 Flask SQLAlchemy 正常工作?
示例代码
这是我设置烧瓶应用程序并保存 SQLAlchemy db 对象的地方:
from flask import Flask
from flask_restful import Api
from flask.ext.sqlalchemy import SQLAlchemy
from flask_cors import CORS
import db_conn
flask_app = Flask(__name__)
flask_app.config.from_object('config')
CORS(flask_app)
api = Api(flask_app)
db_conn.db = SQLAlchemy(flask_app)
api.add_resource(SomeClass, '/abc/<some_id>/def')
以下是我创建 ORM 模型的方法:
import db_conn
db = db_conn.db
class MyTable(db.Model):
__tablename__ = 'my_table'
id = db.Column(db.Integer, primary_key=True)
phase = db.Column(db.Integer, nullable=False, default=0)
def set_phase(self, phase):
self.phase = phase
db.session.commit()
这是带有计时器的 API 处理程序和失败的数据库调用:
from flask_restful import Resource
from threading import Timer
from models import MyTable
import db_conn
import global_store
class SomeClass(Resource):
def put(self, some_id):
global_store.saved_id = some_id
self.timer = Timer(60, self.callback)
return '', 204
def callback(self):
row = MyTable.query.filter_by(id=global_store.saved_id).one()
# sometimes this works, sometimes it doesn't
row.set_phase(1)
db_conn.db.session.commit()
【问题讨论】:
-
此示例看起来不完整,您没有向 sqlalchemy 会话添加任何内容。您能否发布一个执行查询然后尝试执行更新的示例?
-
@snowballhg 好的,我继续添加更多细节。
标签: python database multithreading flask-sqlalchemy flask-restful