Я прочитал много разных блогов, объясняющих, как объединить Flask и сельдерей. Я также прочитал множество вопросов по этой теме. Однако прошли дни, и мне все еще не удается решить эту «RuntimeError: Работа вне контекста приложения», и я не знаю, что я могу сделать, чтобы решить эту проблему на данный момент.
Проект выполняется так:
/ application
- __ init __
- модели
- маршруты
- tfidf_matching
- celery_worker
- config
- wsgi
Я реализовал свой проект, чтобы иметь архитектуру Factory, как это было сделано на это статья . Затем была реализована реализация сельдерея, чтобы соответствовать архитектуре Factory, как описано в этой статье 1030 *.
HTTP-запрос обрабатывается вways.py и вызовет задачу сельдерея, которая будет выполняться в фоновом режиме. Тем временем приложение может продолжать работать и делать другие вещи. Он отправит POST HTTP с другой функцией, и когда задача сельдерея будет выполнена, он отправит POST HTTP результата сельдерея.
rout.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. Models - это база данных 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.
Редактировать
При изменении from flask import current_app as app
, как предложено Мигелем, Ошибка исчезает.
Я изменил импорт на from wsgi import app
в rout.py, но это не работает. Мой экземпляр приложения должен быть импортирован другим способом, но я не знаю, как
При запуске flask с: flask run я получаю следующую трассировку
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)