You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask整合Celery启动Worker报错:urls必须以斜杠开头

启动Celery Worker时触发Flask-RESTx路由格式错误

我在Flask中集成Celery,执行命令celery -A src.celery_worker.celery_app worker --loglevel=debug启动Worker时,抛出错误:

Couldn't import 'src.celery_worker.celery_app': urls must start with a leading slash

完整回溯信息

Traceback (most recent call last):
  File "/home/sonnc/project/mac/lifescience-operator-management-bff/venv/lib/python3.8/site-packages/celery/bin/celery.py", line 58, in convert
    return find_app(value)
  File "/home/sonnc/project/mac/lifescience-operator-management-bff/venv/lib/python3.8/site-packages/celery/app/utils.py", line 383, in find_app
    sym = symbol_by_name(app, imp=imp)
  File "/home/sonnc/project/mac/lifescience-operator-management-bff/venv/lib/python3.8/site-packages/kombu/utils/imports.py", line 61, in symbol_by_name
    reraise(ValueError,
  File "/home/sonnc/project/mac/lifescience-operator-management-bff/venv/lib/python3.8/site-packages/kombu/exceptions.py", line 34, in reraise
    raise value.with_traceback(tb)
  File "/home/sonnc/project/mac/lifescience-operator-management-bff/venv/lib/python3.8/site-packages/kombu/utils/imports.py", line 59, in symbol_by_name
    module = imp(module_name, package=package, **kwargs)
  File "/home/sonnc/project/mac/lifescience-operator-management-bff/venv/lib/python3.8/site-packages/celery/utils/imports.py", line 109, in import_from_cwd
    return imp(module, package=package)
  File "/usr/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 961, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 848, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/home/sonnc/project/mac/lifescience-operator-management-bff/src/__init__.py", line 42, in <module>
    api = Api(
  File "/home/sonnc/project/mac/lifescience-operator-management-bff/venv/lib/python3.8/site-packages/flask_restx/api.py", line 197, in __init__
    self.init_app(app)
  File "/home/sonnc/project/mac/lifescience-operator-management-bff/venv/lib/python3.8/site-packages/flask_restx/api.py", line 236, in init_app
    self._init_app(app)
  File "/home/sonnc/project/mac/lifescience-operator-management-bff/venv/lib/python3.8/site-packages/flask_restx/api.py", line 247, in _init_app
    self._register_doc(self.blueprint or app)
  File "/home/sonnc/project/mac/lifescience-operator-management-bff/venv/lib/python3.8/site-packages/flask_restx/api.py", line 320, in _register_doc
    app_or_blueprint.add_url_rule(self._doc, "doc", self.render_doc)
  File "/home/sonnc/project/mac/lifescience-operator-management-bff/venv/lib/python3.8/site-packages/flask/scaffold.py", line 56, in wrapper_func
    return f(self, *args, **kwargs)
  File "/home/sonnc/project/mac/lifescience-operator-management-bff/venv/lib/python3.8/site-packages/flask/app.py", line 1083, in add_url_rule
    rule = self.url_rule_class(rule, methods=methods, **options)
  File "/home/sonnc/project/mac/lifescience-operator-management-bff/venv/lib/python3.8/site-packages/werkzeug/routing.py", line 698, in __init__
    raise ValueError("urls must start with a leading slash")
ValueError: Couldn't import 'src.celery_worker.celery_app': urls must start with a leading slash

src/celery_worker/__init__.py代码

import os
from flask import Flask

from celery import Celery, Task


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__)
    # url for local redis
    # redis_url = "redis://localhost:6379"
    # url for docker redis
    # redis_url = "redis://redis:6379/0"
    app.config.from_mapping(
        CELERY=dict(
            broker_url="redis://localhost:6379",
            result_backend="redis://localhost:6379",
            task_ignore_result=True,
            # import the tasks
            # imports=("src.common.send_email",),
        ),
    )
    app.config.from_prefixed_env()
    celery_init_app(app)
    return app


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

错误看似和flask_restx模块相关,但找不到具体触发原因。

编辑1:已确认源代码中所有route和path均以斜杠开头(附截图证明),问题仍未解决,求排查。


问题根源

从回溯可以定位到:错误是在Flask-RESTx初始化Api对象时,注册文档路由(self._doc)时触发的——这个文档路径没有以斜杠开头,导致Werkzeug抛出路由格式错误。而Celery启动时会导入整个Flask应用上下文,因此触发了这个初始化阶段的错误。

解决方法

1. 检查并修正Flask-RESTx Api的doc参数

打开src/__init__.py中初始化Api的代码(回溯指向第42行),确认是否显式设置了doc参数,且值是否以斜杠开头:

# 错误写法:doc参数无前置斜杠
api = Api(app, doc="docs")
# 正确写法:添加前置斜杠
api = Api(app, doc="/docs")

如果没有显式设置doc,建议手动指定带斜杠的文档路径,避免默认路径因版本或配置问题出现异常。

2. 隔离Celery与Flask的非必要组件

Celery启动不需要加载Flask的API路由和文档组件,可以重构代码,让Celery使用极简版Flask应用:

  • 修改src/celery_worker/__init__.py,创建仅包含核心配置的Flask应用,不导入Flask-RESTx:
    import os
    from flask import Flask
    from celery import Celery, Task
    
    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_celery_app() -> Flask:
        # 仅初始化核心Flask配置,不加载API相关组件
        app = Flask(__name__)
        app.config.from_mapping(
            CELERY=dict(
                broker_url="redis://localhost:6379",
                result_backend="redis://localhost:6379",
                task_ignore_result=True,
                # imports=("src.common.send_email",),
            ),
        )
        app.config.from_prefixed_env()
        celery_init_app(app)
        return app
    
    flask_app = create_celery_app()
    celery_app = flask_app.extensions["celery"]
    
  • 把包含Flask-RESTx的完整应用放在单独模块(比如src/app.py),仅用于启动Web服务,Celery只依赖极简版应用。

3. 升级Flask-RESTx版本

旧版本Flask-RESTx可能存在路径处理的bug,尝试升级到最新稳定版:

pip install --upgrade flask-restx

内容的提问来源于stack exchange,提问作者fudu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 23:14:54