Flask/Celery: AttributeError("Can't pickle local object 'celery_init_app.<locals>.FlaskTask'")

huangapple go评论114阅读模式
英文:

Flask/Celery: AttributeError("Can't pickle local object 'celery_init_app.<locals>.FlaskTask'")

问题

python 3.10Windows 10 Pro 上的 venv 中运行。

我正在尝试按照 CeleryFlask 集成的教程进行操作: https://flask.palletsprojects.com/en/latest/patterns/celery/

# example.py

from celery import Celery, Task
from flask import Flask


def celery_init_app(app: Flask) -> Celery:
    class FlaskTask(Task):
        def __call__(self, *args: object, **kwargs: object) -> object:
            with app.app_context():
                return self.run(*args, **kwargs)

    celery_app = Celery(app.name, task_cls=FlaskTask)
    celery_app.config_from_object(app.config["CELERY"])
    celery_app.set_default()
    app.extensions["celery"] = celery_app
    return celery_app


def create_app() -> Flask:
    app = Flask(__name__)
    app.config.from_mapping(
        CELERY=dict(
            # Redis Docker container connection string
            broker_url="redis://default:redispw@localhost:55000",
            result_backend="redis://default:redispw@localhost:55000",
            task_ignore_result=True,
        ),
    )
    app.config.from_prefixed_env()
    celery_init_app(app)
    return app
# make_celery.py

from example import create_app

flask_app = create_app()
celery_app = flask_app.extensions["celery"]

命令行调用:
celery -A make_celery worker --loglevel INFO

遇到以下错误:

无法恢复的错误: AttributeError("无法对本地对象 'celery_init_app.<locals>.FlaskTask' 进行 Pickle 处理")
[...]
.venv\lib\site-packages\billiard\reduction.py", line 123, in steal_handle
    return _winapi.DuplicateHandle(
PermissionError: [WinError 5] 拒绝访问

在示例存储库上也发生相同的错误和跟踪:
https://github.com/pallets/flask/tree/main/examples/celery

如何解决这个问题?
有哪些可用的替代方案?

尝试将 class FlaskTask(Task) 移出 celery_init_app 函数的局部范围,但那样显然会失去对 app 变量的访问。

英文:

python 3.10 running in venv on Windows 10 pro.

I am trying to follow the tutorial for the Celery and Flask integration: https://flask.palletsprojects.com/en/latest/patterns/celery/

# example.py

from celery import Celery, Task
from flask import Flask


def celery_init_app(app: Flask) -&gt; Celery:
    class FlaskTask(Task):
        def __call__(self, *args: object, **kwargs: object) -&gt; object:
            with app.app_context():
                return self.run(*args, **kwargs)

    celery_app = Celery(app.name, task_cls=FlaskTask)
    celery_app.config_from_object(app.config[&quot;CELERY&quot;])
    celery_app.set_default()
    app.extensions[&quot;celery&quot;] = celery_app
    return celery_app


def create_app() -&gt; Flask:
    app = Flask(__name__)
    app.config.from_mapping(
        CELERY=dict(
            # Redis Docker container connection string
            broker_url=&quot;redis://default:redispw@localhost:55000&quot;,
            result_backend=&quot;redis://default:redispw@localhost:55000&quot;,
            task_ignore_result=True,
        ),
    )
    app.config.from_prefixed_env()
    celery_init_app(app)
    return app
# make_celery.py

from example import create_app

flask_app = create_app()
celery_app = flask_app.extensions[&quot;celery&quot;]

Command line call:
celery -A make_celery worker --loglevel INFO

Runs into:

Unrecoverable error: AttributeError(&quot;Can&#39;t pickle local object &#39;celery_init_app.&lt;locals&gt;.FlaskTask&#39;&quot;)
[...]
.venv\lib\site-packages\billiard\reduction.py&quot;, line 123, in steal_handle
    return _winapi.DuplicateHandle(
PermissionError: [WinError 5] Access is denied

The same error and traceback occurs on the example repo:
https://github.com/pallets/flask/tree/main/examples/celery

How can I resolve this?
What alternatives are available?

Tried moving the class FlaskTask(Task) out of the local scope of the celery_init_app function, but then I obviously lose access to the app variable.

答案1

得分: 4

我遇到了相同的问题。将celery_init_app 更改为以下方式可以解决它:

celery_app = Celery(app.name)
celery_app.config_from_object(app.config["CELERY"])
celery_app.Task = FlaskTask

我希望我能解释一下为什么要这样做。如果有人知道,请发布。

英文:

I ran into the same issue. Changing celery_init_app to read like this fixed it

celery_app = Celery(app.name)
celery_app.config_from_object(app.config[&quot;CELERY&quot;])
celery_app.Task = FlaskTask

I wish I could give an explanation as to the "why". If anybody knows please post it

huangapple
  • 本文由 发表于 2023年3月7日 16:55:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/75659790.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定