有点神秘。
当所有代码都放在单个app.py
文件中时,从flask app中生成一个线程工作得很好,但是当使用工厂模式时,应用程序上下文会丢失。
Exception in thread Thread-2:
Traceback (most recent call last):
File "/XXX/flaskthreading/venv/lib/python3.9/site-packages/sqlalchemy/util/_collections.py", line 1008, in __call__
127.0.0.1 - - [07/Jun/2022 14:06:53] "GET / HTTP/1.1" 200 -
return self.registry[key]
KeyError: <greenlet.greenlet object at 0x7f4f541ad040 (otid=0x7f4f54199d00) current active started main>
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.9/threading.py", line 954, in _bootstrap_inner
self.run()
File "/usr/lib/python3.9/threading.py", line 892, in run
self._target(*self._args, **self._kwargs)
File "/XXX/flaskthreading/app2/views.py", line 12, in printer
print(User.query.all())
File "/XXX/flaskthreading/venv/lib/python3.9/site-packages/flask_sqlalchemy/__init__.py", line 552, in __get__
return type.query_class(mapper, session=self.sa.session())
File "/XXX/flaskthreading/venv/lib/python3.9/site-packages/sqlalchemy/orm/scoping.py", line 47, in __call__
sess = self.registry()
File "/XXX/flaskthreading/venv/lib/python3.9/site-packages/sqlalchemy/util/_collections.py", line 1010, in __call__
return self.registry.setdefault(key, self.createfunc())
File "/XXX/flaskthreading/venv/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 4225, in __call__
return self.class_(**local_kw)
File "/XXX/flaskthreading/venv/lib/python3.9/site-packages/flask_sqlalchemy/__init__.py", line 174, in __init__
self.app = app = db.get_app()
File "/XXX/flaskthreading/venv/lib/python3.9/site-packages/flask_sqlalchemy/__init__.py", line 1042, in get_app
raise RuntimeError(
RuntimeError: No application found. Either work inside a view function or push an application context. See http://flask-sqlalchemy.pocoo.org/contexts/.
知道为什么会发生这种情况,或者我们错过了什么文档吗?MVP提供https://github.com/bodik/flaskthreading-experiments/
git clone
pip install -r requirements.txt
# working app
FLASK_APP=app1 flask run
curl http://localhost:5000/
# produces error
FLASK_APP=app2.app flask run
curl http://localhost:5000/
From https://flask.palletsprojects.com/en/2.1.x/reqcontext/#lifetime-of-the-context:
当一个Flask应用程序开始处理一个请求时,它会推送一个请求上下文,这个请求上下文也会推送一个应用上下文。当请求结束时,它先弹出请求上下文,然后弹出应用程序上下文。
上下文对于每个线程(或其他worker类型)是唯一的. ...
在全局app
和db = SQLAlchemy(app)
的情况下,db
总是有self.app
在应用程序工厂模式的情况下,db
从线程获取应用程序上下文
传递一个AppContext
到线程:
# def printer(): # Change this
def printer(app_context): # to this
app_context.push() #
print(User.query.all())
@blueprint.route('/')
def index():
# athread = Thread(target=printer, args=(), daemon=True) # Change this
athread = Thread(target=printer, args=(current_app.app_context(),), daemon=True) # to this
athread.start()
return 'ok'