【问题标题】:Problems by running celery apply_async from flask app从烧瓶应用程序运行 celery apply_async 的问题
【发布时间】:2020-11-04 05:18:27
【问题描述】:

这是我的第一个烧瓶和芹菜项目。我的 Flask 应用程序有一个运行时间很长的进程,所以我尝试使用 Celery 异步运行它。 基本上代码需要根据请求生成文件。 完成后,应将用户重定向到可以下载此文件的页面。 作为 AMQP,我使用 Rabbitmq。 我的项目结构如下:

Project/
|-- flasK.py
|-- asynC.py
|--db.sqlite3    
|
|-- templates/
|   |-- index.html
|   |-- done.html
|   |-- inProc.html
|
|-- |-- static/
    |-- css(empty)
    |-- js(empty)

运行烧瓶服务器的脚本,flasK.py:

from asy import createSAV_2
from flask import Flask, render_template, url_for, request, redirect, send_file, send_from_directory, safe_join, abort
from celery.result import AsyncResult

flask_app = Flask(__name__)

@flask_app.route('/', methods=['POST', 'GET'])
def index():
    if request.method == 'POST':
        #createSAV_2.apply_async((2, 2), queue='test')
        createSAV_2.delay(2, 2)

        return render_template("inProc.html")
    else:
        pass
    return render_template("index.html")


if __name__ == '__main__':
    flask_app.run(port=8080, debug=True)

运行 Celery 的代码,asynC.py:

from celery import Celery
from time import sleep
from celery.result import AsyncResult
from flask import render_template

app = Celery('asy', broker='pyamqp://guest@localhost//', backend='db+sqlite:///db.sqlite3')

@app.task(name='createSAV_2')
def createSAV_2 (a, b):
    sleep(5)
    return render_template("done.html")

在我运行服务器并尝试模拟数据请求后,我得到了这个错误:

[2020-11-01 13:44:41,545: ERROR/ForkPoolWorker-2] Task createSAV_2[93a094c7-2315-4016-8deb-acffae18f0ef] raised unexpected: AttributeError("'NoneType' object has no attribute 'app'")
    Traceback (most recent call last):
      File "/Users/bbk/Desktop/labelingTool_v1/tool_v0/venv/lib/python3.7/site-packages/celery/app/trace.py", line 409, in trace_task
        R = retval = fun(*args, **kwargs)
      File "/Users/bbk/Desktop/labelingTool_v1/tool_v0/venv/lib/python3.7/site-packages/celery/app/trace.py", line 701, in __protected_call__
        return self.run(*args, **kwargs)
      File "/Users/bbk/Desktop/labelingTool_v1/tool_v0/asy.py", line 11, in createSAV_2
        return render_template("done.html")
      File "/Users/bbk/Desktop/labelingTool_v1/tool_v0/venv/lib/python3.7/site-packages/flask/templating.py", line 136, in render_template
        ctx.app.update_template_context(context)
    AttributeError: 'NoneType' object has no attribute 'app' 

如果我使用 .apply_async 而不是 .delay,我不会收到任何错误或其他消息。

Celery 正在运行,如果我尝试运行文档中的示例代码: https://docs.celeryproject.org/en/stable/getting-started/first-steps-with-celery.html 那么它工作正常。

如果您有任何想法/建议,请告诉我

【问题讨论】:

  • 你为什么在 celery 任务中调用 render_template() ?就您而言,如果您想等待任务,为什么要使用 apply_async ? celery+apply_async 的全部目的是不等待任务的响应。您遇到此错误是因为您尝试从完全不知道的 python 进程中使用 Flask 上下文(带有模板和内容)。要解决此问题,只需从您的任务中删除返回行。
  • 你为什么在 celery 任务中调用 render_template() ? ->因为我遵循 celery 文档中的代码。如果要等待任务,为什么要使用 apply_async ? ->我想显示一个页面“请稍候,文件正在处理中”,文件完成后,用户应该被重定向到下载页面。要解决此问题,只需从您的任务中删除返回行。 ->结果是一样的。
  • 我认为您不应该将 Celery 用于此用途,Celery 用于在另一台服务器或实例上运行异步任务。要修复您的错误,请不要在 asy.py 中使用任何烧瓶导入并继续使用 .delay() 但在这种情况下 celery 是无用的,因为您可以调用 createSAV_2() 方法。如果你真的想这样做,因为createSAV_2 可能需要一段时间,你应该使用 apply_async 生成一个任务并实现一个循环来等待任务结束......所以它与使用延迟()......总结我不确定 Celery 在您的特定情况下是否有用。一开始就保持简单。

标签: python flask celery


【解决方案1】:

您不应该将 Celery 用于此用途,Celery 用于在另一个服务器或实例上运行异步任务。

要修复您的错误,请不要在 asy.py 中使用任何 Flask 导入并继续使用 .delay() 但在这种情况下 celery 是无用的,因为您可以调用 createSAV_2() 方法。

如果您真的想这样做,因为createSAV_2() 可能需要一段时间,您应该使用apply_async() 生成一个任务并实现一个循环来等待任务结束。所以和使用delay()差不多...

总而言之,我不确定 Celery 在您的特定情况下是否有用。一开始就保持简单。

(评论转换为答案)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-13
    • 1970-01-01
    • 2015-04-18
    • 2020-03-16
    • 2015-07-05
    相关资源
    最近更新 更多