如何在Flask中禁用线程?

时间:2018-09-20 16:25:08

标签: python multithreading flask gunicorn

我有以下代码:

import sqlite3
from flask import Flask

app = Flask(__name__)
db = sqlite3.connect('/etc/db.sqlite')

@app.route('/')
def handle():
    # run a query and return a response

if __name__ == '__main__':
    app.run('0.0.0.0', 8080, debug=True)

但是,当我尝试在请求处理程序中对数据库对象执行某些操作时,我从sqlite3收到以下异常,因为它不是线程安全的库,并且查询是从Flask产生的另一个线程运行的,而不是来自主线程:

sqlite3.ProgrammingError: SQLite objects created in a thread can only be used in that same thread.The object was created in thread id 139886422697792 and this is thread id 139886332843776

我知道执行此操作的“正确”方法是具有创建sqlite3.Connection对象实例并将其存储在Flask g全局实例中的功能,如下所示:{ {3}}。但是,在生产环境中运行此应用程序时,我使用gunicorn -w 4 -b 0.0.0.0:8080 app:app,并且在那里工作正常,因为在这种情况下,线程是在开始时生成的。

尽管Flask g全局方法在所有情况下都有效,但我真的想避免在每个请求中创建和销毁sqlite3.Connection对象的开销。因此,我想在Flask中禁用线程,以便上面的代码可以运行而不会引起问题。

但是,即使将以上代码的最后一行更改为app.run(..., threaded=False),也无法避免此错误。似乎Flask仍然产生了一个用于处理请求的线程。

那么,如何禁用Flask的线程?

2 个答案:

答案 0 :(得分:2)

请勿在烧瓶中直接使用sqlite3模块。使用Flask_sqlalchemy 尝试在没有它的sqlite上建立数据库时遇到很多麻烦。一旦我进行了切换,那就太容易了。您也可以连接到多种类型的SQL数据库!

烧瓶sqlalchemy:

http://flask-sqlalchemy.pocoo.org/2.3/

真的是烧瓶的最佳指南:

https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-iv-database

答案 1 :(得分:1)

使用scoped_session可以避免这种情况:

session = scoped_session(sessionmaker(bind=engine))()