RuntimeError: Working outside of application context with Celery and Flask in Python
RuntimeError: Working outside of application context with Celery and Flask in Python
我读过许多解释如何结合使用 Flask 和 Celery 的不同博客。我还阅读了大量有关该主题的堆栈问题。然而,已经好几天了,我还是没能解决这个问题"RuntimeError: Working outside of application context",我不知道现在我能做些什么来解决这个问题。
项目是这样完成的:
/申请
- __ init__
- 型号
- 路线
- tfidf_matching
- celery_worker
- 配置
- wsgi
我实现了我的项目以拥有工厂架构,就像在 article. Then, the celery implementation has been done to fit this Factory architecture as explained on this article 上所做的那样。
HTTP 请求在 routes.py 中处理,将调用一个 celery 任务在后台完成。与此同时,该应用程序可以继续 运行 并执行其他操作。它将发送带有另一个功能的 POST HTTP,当 celery 任务完成时,它将发送 celery 结果的 POST HTTP。
routes.py包含以下内容,我已将其简化为重要部分:
from flask import request, make_response, jsonify, copy_current_request_context
from flask import current_app as app
from application import tfidf_matching
import time
from application.models import db, Status
from app import cel
def snooze(maxTime):
...
@app.before_first_request
def default_values():
...
@cel.task
def tfidf(question):
with app.app_context:
answer = tfidf_matching.getMatchingSentence(question)
...
return answer
@app.route('/webhook', methods=['GET', 'POST'])
def webhook():
req = request.get_json(force=True)
...
if ... :
user_input = req.get('queryResult').get('queryText')
answer = tfidf.apply_async(args=[user_input], expires=60)
...
snooze(4)
response = {'followupEventInput': {'name': 'snooze'}}
if ...:
response = {'fulfillmentText': answer}
return make_response(jsonify(response))
我尝试使用@copy_current_request_context 和 app.app_context 来解决其他堆栈溢出问题中建议的错误,但没有成功。
Celery 使用以下命令启动:
celery worker -A celery_worker.cel --loglevel=info
celery_worker.py 包含以下内容:
import os
from app.routes import tfidf
from application import cel, create_app
app = create_app(os.getenv('FLASK_CONFIG') or 'default')
app.app_context().push()
我不确定是否有必要,但以防万一我还添加了 init 和 wsgi 内容。模型是一个 SQLAlchemy 数据库,这似乎不相关,所以我不会添加这部分。
__ init__.py 包含以下内容:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from celery import Celery
from config import config, Config
db = SQLAlchemy()
cel = Celery(__name__, broker=Config.broker_url, backend=Config.result_backend)
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
db.init_app(app)
app.config.update(
broker_url='redis://localhost:6379',
result_backend='redis://localhost:6379',
SQLALCHEMY_DATABASE_URI='postgresql://postgres:APG@localhost:5432/Dialogflow',
SQLALCHEMY_TRACK_MODIFICATIONS='None'
)
cel.conf.update(
result_expires=3600,
)
cel.conf.update(app.config)
with app.app_context():
from . import routes
db.create_all()
return app
并且 wsgi.py 包含以下内容:
import os
from application import create_app
app = create_app(os.getenv('FLASK_CONFIG') or 'default')
if __name__ == "__main__":
app.run(host='0.0.0.0')
最后,这是堆栈跟踪:
Traceback (most recent call last):
File "c:\users\emma\appdata\local\programs\python\python37\lib\runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "c:\users\emma\appdata\local\programs\python\python37\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "C:\Users\Emma\AppData\Local\Programs\Python\Python37\Scripts\celery.exe\__main__.py", line 7, in <module>
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\celery\__main__.py", line 16, in main
_main()
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\celery\bin\celery.py", line 322, in main
cmd.execute_from_commandline(argv)
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\celery\bin\celery.py", line 495, in execute_from_commandline
super(CeleryCommand, self).execute_from_commandline(argv)))
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\celery\bin\base.py", line 289, in execute_from_commandline
argv = self.setup_app_from_commandline(argv)
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\celery\bin\base.py", line 509, in setup_app_from_commandline
self.app = self.find_app(app)
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\celery\bin\base.py", line 531, in find_app
return find_app(app, symbol_by_name=self.symbol_by_name)
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\celery\app\utils.py", line 373, in find_app
sym = symbol_by_name(app, imp=imp)
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\celery\bin\base.py", line 534, in symbol_by_name
return imports.symbol_by_name(name, imp=imp)
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\kombu\utils\imports.py", line 57, in symbol_by_name
module = imp(module_name, package=package, **kwargs)
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\celery\utils\imports.py", line 111, in import_from_cwd
return imp(module, package=package)
File "c:\users\emma\appdata\local\programs\python\python37\lib\importlib\__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 728, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "C:\Users\Emma\PycharmProjects\APG_Dialogflow\celery_worker.py", line 2, in <module>
from application.routes import tfidf
File "C:\Users\Emma\PycharmProjects\APG_Dialogflow\application\routes.py", line 21, in <module>
@app.before_first_request
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\werkzeug\local.py", line 348, in __getattr__
return getattr(self._get_current_object(), name)
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\werkzeug\local.py", line 307, in _get_current_object
return self.__local()
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\flask\globals.py", line 52, in _find_app
raise RuntimeError(_app_ctx_err_msg)
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that needed
to interface with the current application object in some way. To solve
this, set up an application context with app.app_context(). See the
documentation for more information.
编辑
按照 Miguel 的建议更改 from flask import current_app as app
,错误就消失了。
我在 routes.py 中将导入更改为 from wsgi import app
,但这不起作用。我的应用程序实例应该以另一种方式导入,但我不知道如何导入
当 运行ning flask with : flask 运行
我得到以下回溯
Traceback (most recent call last):
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\flask\cli.py", line 240, in locate_app
__import__(module_name)
File "C:\Users\Emma\PycharmProjects\APG_Dialogflow\wsgi.py", line 4, in <module>
app = create_app(os.getenv('FLASK_CONFIG') or 'default')
File "C:\Users\Emma\PycharmProjects\APG_Dialogflow\application\__init__.py", line 28, in create_app
from . import routes
File "C:\Users\Emma\PycharmProjects\APG_Dialogflow\application\routes.py", line 6, in <module>
from wsgi import app
ImportError: cannot import name 'app' from 'wsgi' (C:\Users\Emma\PycharmProjects\APG_Dialogflow\wsgi.py)
问题是你的代码中有这个:
from flask import current_app as app
然后在 @app.route
和 @app.before_first_request
中使用 app
。
这是不正确的,Flask 无法确定您的应用程序实例是什么。您需要做的是使用真实的应用程序实例而不是 current_app
.
您可以在视图函数中使用 current_app
,因为 Flask 会为您设置应用程序上下文,但您不能在应用程序的全局范围内使用它。
更新后更新到答案:
你现在怎么循环依赖的问题。请注意最后的堆栈跟踪如何显示 wsgi.py
,进入 application/__init__.py
,然后进入 application/routes.py
,最后返回 wsgi.py
.
Flask 应用程序中此问题的一个相当常见的解决方案是将 application/__init__.py
文件中的 from . import routes
一直移动到 .文件的底部。我相信这将消除循环依赖。
我读过许多解释如何结合使用 Flask 和 Celery 的不同博客。我还阅读了大量有关该主题的堆栈问题。然而,已经好几天了,我还是没能解决这个问题"RuntimeError: Working outside of application context",我不知道现在我能做些什么来解决这个问题。
项目是这样完成的:
/申请
- __ init__
- 型号
- 路线
- tfidf_matching
- celery_worker
- 配置
- wsgi
我实现了我的项目以拥有工厂架构,就像在 article. Then, the celery implementation has been done to fit this Factory architecture as explained on this article 上所做的那样。
HTTP 请求在 routes.py 中处理,将调用一个 celery 任务在后台完成。与此同时,该应用程序可以继续 运行 并执行其他操作。它将发送带有另一个功能的 POST HTTP,当 celery 任务完成时,它将发送 celery 结果的 POST HTTP。
routes.py包含以下内容,我已将其简化为重要部分:
from flask import request, make_response, jsonify, copy_current_request_context
from flask import current_app as app
from application import tfidf_matching
import time
from application.models import db, Status
from app import cel
def snooze(maxTime):
...
@app.before_first_request
def default_values():
...
@cel.task
def tfidf(question):
with app.app_context:
answer = tfidf_matching.getMatchingSentence(question)
...
return answer
@app.route('/webhook', methods=['GET', 'POST'])
def webhook():
req = request.get_json(force=True)
...
if ... :
user_input = req.get('queryResult').get('queryText')
answer = tfidf.apply_async(args=[user_input], expires=60)
...
snooze(4)
response = {'followupEventInput': {'name': 'snooze'}}
if ...:
response = {'fulfillmentText': answer}
return make_response(jsonify(response))
我尝试使用@copy_current_request_context 和 app.app_context 来解决其他堆栈溢出问题中建议的错误,但没有成功。
Celery 使用以下命令启动:
celery worker -A celery_worker.cel --loglevel=info
celery_worker.py 包含以下内容:
import os
from app.routes import tfidf
from application import cel, create_app
app = create_app(os.getenv('FLASK_CONFIG') or 'default')
app.app_context().push()
我不确定是否有必要,但以防万一我还添加了 init 和 wsgi 内容。模型是一个 SQLAlchemy 数据库,这似乎不相关,所以我不会添加这部分。
__ init__.py 包含以下内容:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from celery import Celery
from config import config, Config
db = SQLAlchemy()
cel = Celery(__name__, broker=Config.broker_url, backend=Config.result_backend)
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
db.init_app(app)
app.config.update(
broker_url='redis://localhost:6379',
result_backend='redis://localhost:6379',
SQLALCHEMY_DATABASE_URI='postgresql://postgres:APG@localhost:5432/Dialogflow',
SQLALCHEMY_TRACK_MODIFICATIONS='None'
)
cel.conf.update(
result_expires=3600,
)
cel.conf.update(app.config)
with app.app_context():
from . import routes
db.create_all()
return app
并且 wsgi.py 包含以下内容:
import os
from application import create_app
app = create_app(os.getenv('FLASK_CONFIG') or 'default')
if __name__ == "__main__":
app.run(host='0.0.0.0')
最后,这是堆栈跟踪:
Traceback (most recent call last):
File "c:\users\emma\appdata\local\programs\python\python37\lib\runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "c:\users\emma\appdata\local\programs\python\python37\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "C:\Users\Emma\AppData\Local\Programs\Python\Python37\Scripts\celery.exe\__main__.py", line 7, in <module>
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\celery\__main__.py", line 16, in main
_main()
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\celery\bin\celery.py", line 322, in main
cmd.execute_from_commandline(argv)
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\celery\bin\celery.py", line 495, in execute_from_commandline
super(CeleryCommand, self).execute_from_commandline(argv)))
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\celery\bin\base.py", line 289, in execute_from_commandline
argv = self.setup_app_from_commandline(argv)
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\celery\bin\base.py", line 509, in setup_app_from_commandline
self.app = self.find_app(app)
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\celery\bin\base.py", line 531, in find_app
return find_app(app, symbol_by_name=self.symbol_by_name)
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\celery\app\utils.py", line 373, in find_app
sym = symbol_by_name(app, imp=imp)
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\celery\bin\base.py", line 534, in symbol_by_name
return imports.symbol_by_name(name, imp=imp)
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\kombu\utils\imports.py", line 57, in symbol_by_name
module = imp(module_name, package=package, **kwargs)
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\celery\utils\imports.py", line 111, in import_from_cwd
return imp(module, package=package)
File "c:\users\emma\appdata\local\programs\python\python37\lib\importlib\__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 728, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "C:\Users\Emma\PycharmProjects\APG_Dialogflow\celery_worker.py", line 2, in <module>
from application.routes import tfidf
File "C:\Users\Emma\PycharmProjects\APG_Dialogflow\application\routes.py", line 21, in <module>
@app.before_first_request
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\werkzeug\local.py", line 348, in __getattr__
return getattr(self._get_current_object(), name)
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\werkzeug\local.py", line 307, in _get_current_object
return self.__local()
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\flask\globals.py", line 52, in _find_app
raise RuntimeError(_app_ctx_err_msg)
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that needed
to interface with the current application object in some way. To solve
this, set up an application context with app.app_context(). See the
documentation for more information.
编辑
按照 Miguel 的建议更改 from flask import current_app as app
,错误就消失了。
我在 routes.py 中将导入更改为 from wsgi import app
,但这不起作用。我的应用程序实例应该以另一种方式导入,但我不知道如何导入
当 运行ning flask with : flask 运行 我得到以下回溯
Traceback (most recent call last):
File "c:\users\emma\appdata\local\programs\python\python37\lib\site-packages\flask\cli.py", line 240, in locate_app
__import__(module_name)
File "C:\Users\Emma\PycharmProjects\APG_Dialogflow\wsgi.py", line 4, in <module>
app = create_app(os.getenv('FLASK_CONFIG') or 'default')
File "C:\Users\Emma\PycharmProjects\APG_Dialogflow\application\__init__.py", line 28, in create_app
from . import routes
File "C:\Users\Emma\PycharmProjects\APG_Dialogflow\application\routes.py", line 6, in <module>
from wsgi import app
ImportError: cannot import name 'app' from 'wsgi' (C:\Users\Emma\PycharmProjects\APG_Dialogflow\wsgi.py)
问题是你的代码中有这个:
from flask import current_app as app
然后在 @app.route
和 @app.before_first_request
中使用 app
。
这是不正确的,Flask 无法确定您的应用程序实例是什么。您需要做的是使用真实的应用程序实例而不是 current_app
.
您可以在视图函数中使用 current_app
,因为 Flask 会为您设置应用程序上下文,但您不能在应用程序的全局范围内使用它。
更新后更新到答案:
你现在怎么循环依赖的问题。请注意最后的堆栈跟踪如何显示 wsgi.py
,进入 application/__init__.py
,然后进入 application/routes.py
,最后返回 wsgi.py
.
Flask 应用程序中此问题的一个相当常见的解决方案是将 application/__init__.py
文件中的 from . import routes
一直移动到 .文件的底部。我相信这将消除循环依赖。