Python中Celery worker启动路径问题如何解决?

django 项目,例如在 /test/server/目录下执行 python manage.py celery worker -l info -c 30 -Ofair
启用了 30 个 worker,使用 pwdx 查看某个 worker 工作路径,显示在 /test/server,一切正常。

因为系统设置了 CELERYD_MAX_TASKS_PER_CHILD = 40 参数,也就是每个 worker 最多接收 40 次任务后就销毁重建。
重建的 worker 使用 pwdx 或者 ls -l /proc/pid/ 方式查看,发现 cwd 目录并不是上述的 /test/server,而是某个任务中曾经读写过的路径。
很奇怪这种现象,使用 CELERYD_CHDIR='/test/server/' 是否就能解决这个问题呢?


Python中Celery worker启动路径问题如何解决?

1 回复

这个问题我遇到过,核心是Celery的启动路径和工作目录不一致导致的模块导入失败。

根本原因:Celery worker启动时,Python的sys.path是基于你执行celery -A命令的当前工作目录(CWD)来解析模块路径的。如果你的项目结构复杂,或者你从项目根目录以外的位置启动worker,就会找不到任务模块。

解决方案(按推荐度排序):

  1. 标准做法:从项目根目录启动 这是最可靠的方式。确保你的项目结构清晰,并在根目录下启动worker。

    # 假设你的项目结构如下:
    # myproject/
    #   celery_app.py
    #   tasks/
    #     __init__.py
    #     email_tasks.py
    # 在myproject/目录下执行:
    celery -A celery_app worker --loglevel=info
    
  2. 使用绝对模块路径(推荐) 在定义Celery应用时,使用完整的导入路径。

    # celery_app.py
    from celery import Celery
    
    # 使用绝对导入路径,而不是相对路径
    app = Celery('myproject',
                 broker='redis://localhost:6379/0',
                 include=['myproject.tasks.email_tasks'])  # 关键在这里
    
  3. 设置PYTHONPATH环境变量 如果你必须从其他目录启动,可以临时设置Python路径。

    # Linux/Mac
    export PYTHONPATH=/path/to/your/project
    celery -A celery_app worker --loglevel=info
    
    # Windows (cmd)
    set PYTHONPATH=C:\path\to\your\project
    celery -A celery_app worker --loglevel=info
    
  4. 在代码中动态修改sys.path(备选) 作为最后手段,可以在Celery应用文件开头添加路径。

    import sys
    from pathlib import Path
    sys.path.insert(0, str(Path(__file__).parent))
    
    from celery import Celery
    app = Celery('myproject')
    

一句话总结:从项目根目录启动worker并使用绝对导入路径是最佳实践。

回到顶部