英文:
Flask/Celery: AttributeError("Can't pickle local object 'celery_init_app.<locals>.FlaskTask'")
问题
python 3.10
在 Windows 10 Pro
上的 venv
中运行。
我正在尝试按照 Celery
和 Flask
集成的教程进行操作: 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) -> 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"]
Command line call:
celery -A make_celery worker --loglevel INFO
Runs into:
Unrecoverable error: AttributeError("Can't pickle local object 'celery_init_app.<locals>.FlaskTask'")
[...]
.venv\lib\site-packages\billiard\reduction.py", 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["CELERY"])
celery_app.Task = FlaskTask
I wish I could give an explanation as to the "why". If anybody knows please post it
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论