在应用程序上下文 Flask Celery 之外工作

Working outside of application context Flask Celery

我会在序言中指出,我知道有一些针对此问题的解决方案,但其中 none 遵循本指南 here 并且似乎没有回答我的问题。

我在 Flask 中的 Celery 应用程序收到此错误。

[2021-11-23 22:50:01,469: ERROR/ForkPoolWorker-1] Task smartful_versioning_flask.test_celery_task[6dda4a4b-cf64-4fdc-8317-237dca9ad31b] raised unexpected: RuntimeError('Working outside of application context.\n\nThis typically means that you attempted to use functionality that needed\nto interface with the current application object in some way. To solve\nthis, set up an application context with app.app_context().  See the\ndocumentation for more information.')
Traceback (most recent call last):
  File "/var/smartful_flask/smartful_venv/lib/python3.7/site-packages/celery/app/trace.py", line 450, in trace_task
    R = retval = fun(*args, **kwargs)
  File "/var/smartful_flask/smartful_venv/lib/python3.7/site-packages/celery/app/trace.py", line 731, in __protected_call__
    return self.run(*args, **kwargs)
  File "/var/smartful_flask/smartful_versioning_flask.py", line 21, in test_celery_task
    return jsonify({"something": "something"})
  File "/var/smartful_flask/smartful_venv/lib/python3.7/site-packages/flask/json/__init__.py", line 336, in jsonify
    if current_app.config["JSONIFY_PRETTYPRINT_REGULAR"] or current_app.debug:
  File "/var/smartful_flask/smartful_venv/lib/python3.7/site-packages/werkzeug/local.py", line 422, in __get__
    obj = instance._get_current_object()
  File "/var/smartful_flask/smartful_venv/lib/python3.7/site-packages/werkzeug/local.py", line 544, in _get_current_object
    return self.__local()  # type: ignore
  File "/var/smartful_flask/smartful_venv/lib/python3.7/site-packages/flask/globals.py", line 47, 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 Flask, jsonify
     from celery import Celery
     
     app = Flask(__name__)
     app.config['CELERY_BROKER_URL'] = 'redis://localhost:6379/0'
     app.config['CELERY_RESULT_BACKEND'] = 'redis://localhost:6379/0'
     
     celery = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
     celery.conf.update(app.config)
     
     @celery.task
     def test_celery_task():
         return jsonify({"something": "something"})
     
     @app.route("/web/start/backend", methods=['POST'])
     def start_task():
         task = test_celery_task.apply_async()
         return task.id
     
     @app.route("/web/check-status/backend/<task_id>", methods=['GET'])
     def check_task(task_id):
         task = test_celery_task.AsyncResult(task_id)
     
         if task.state == 'PENDING':
             return jsonify({
                 "task": task_id,
                 "state": task.state,
                 "data": None,
                 "complete": False,
                 "error": False
             })
         elif task.state == 'SUCCESS':
             print(task.info)
         else:
             print(task.state)
     
         return "task.info"

    if __name__ == "__main__":
        app.run()

正如这里的回溯所预期的那样,任务将失败并且永远不会从后端 return 失败。我正在使用 Ngnix、wsgi、Supervisor 来解决这个问题——尽管无论有没有 supervisor 产生工人,都存在同样的问题。

我确信我忽视了一些愚蠢而微不足道的事情,尽管像往常一样 - 太盲目以至于看不到它。

我在这里找到了修复方法,并为其他有类似情况的人做了标记。这与主管正在使用的工作目录有关。

我进入了我的 flask 应用程序的目录并手动生成了一个 worker:

# smartful_venv/bin/celery --app=smartful_versioning_flask.celery worker --loglevel=DEBUG

我 运行 我的烧瓶应用程序如问题所示,我的 return 打印成功。我的情况可能是 Supervisor 无权访问我正在使用的工作目录。虽然没有明确说明,但是主管文档中并没有真正讨论这个问题,尽管主管报告说它是 运行 root - 它是谎言!

编辑添加:

在另一个任务中,我需要在执行任何操作之前添加 with app.app_context():。这对我来说很奇怪,但它有效。如果有人能解释为什么应用程序上下文只存在于 with 之后,可能会引发健康的讨论。