celery.py必须与settings.py同级,位于Django项目包根目录(如myproject/myproject/celery.py),不可放在app目录或manage.py同级任意位置;其核心作用是定义Celery应用实例,通过os.environ.setdefault设置Django配置模块,调用app.config_from_object加载CELERY_前缀配置,并启用app.autodiscover_tasks()自动扫描各app下的tasks.py。

celery.py 文件必须放在 Django 项目包根目录下
不是 app 目录,也不是 manage.py 同级的任意位置——它得和 settings.py 在同一级,比如你的项目叫 myproject,结构必须是:
myproject/ ├── myproject/ │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── <strong>celery.py</strong> ← 就这儿 ├── manage.py否则 Celery 启动时找不到配置,
celery -A myproject worker 会报 ModuleNotFoundError: No module named 'myproject.celery' 或静默失败。
这个文件本质是 Celery 实例的“入口”,Django 并不自动识别它,但约定俗成地放这里,能让 celery -A 正确加载。内容极简,重点在设置 broker 和 backend:
from celery import Celery
import os
<p>os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')</p><p>app = Celery('myproject')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()注意三点:
-
namespace='CELERY'表示只读取settings.py中以CELERY_开头的配置项(如CELERY_BROKER_URL),避免污染全局配置 -
app.autodiscover_tasks()是关键:它会让 Celery 自动扫描每个 installed app 下的tasks.py,不用手动 import - 别写
broker=...硬编码——交给settings.py管理更安全、易部署
settings.py 中必须配置 CELERY_BROKER_URL 和 CELERY_RESULT_BACKEND
Redis 作为 Broker 和 Result Backend 是最常见组合,但两个 URL 必须用不同 database number,否则任务队列和结果存储会互相覆盖。典型错误是都写成 redis://127.0.0.1:6379/0,导致 AsyncResult.get() 返回 None 或超时。
立即学习“Python免费学习笔记(深入)”;
正确写法(在 settings.py 底部添加):
CELERY_BROKER_URL = 'redis://127.0.0.1:6379/1' CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/2'
其他关键配置项:
-
CELERY_TIMEZONE = 'Asia/Shanghai':必须显式设,否则定时任务按 UTC 执行,和本地时间差 8 小时 -
CELERY_ENABLE_UTC = False:和上面配合,禁用 UTC,避免时区转换混乱 -
CELERY_TASK_TRACK_STARTED = True:让任务状态能被查到(比如task.status == 'STARTED') -
CELERY_TASK_ACKS_LATE = True:worker 崩溃时,未确认的任务会重回队列,防止丢失
启动 worker 前必须确保 redis-server 已运行且端口可访问
常见错误现象:ConnectionRefusedError: Error 10061 connecting to 127.0.0.1:6379,或 worker 启动后立刻退出、无日志。
验证方式(命令行):
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
redis-cli ping
返回 PONG 才算通。如果用 Docker,检查容器是否 up、端口是否映射(-p 6379:6379),别漏掉 redis 服务名在 docker-compose.yml 里拼错。
启动 worker 的命令要带 -A 指向项目名,不是文件名:
- Linux/macOS:
celery -A myproject worker --loglevel=info - Windows:
celery -A myproject worker --loglevel=info -P eventlet(不加-P eventlet会卡住或报ValueError: not enough values to unpack)
别在 app 目录下执行,必须在 manage.py 所在目录运行,否则 Python 路径解析失败。
tasks.py 必须放在每个 app 目录下且命名固定
Celery 不会自动发现 myapp/tasks/tasks.py 或 myapp/my_tasks.py —— 它只认 myapp/tasks.py 这个路径和名字。这是硬编码逻辑,改不了。
一个最小可用示例(myapp/tasks.py):
from celery import shared_task <p>@shared_task def add(x, y): return x + y
调用方式(在 view 或 shell 中):
from myapp.tasks import add result = add.delay(2, 3) # 返回 AsyncResult 对象 print(result.get(timeout=5)) # 输出 5
注意:@shared_task 比 @app.task 更适合 Django,因为它不依赖全局 app 实例,能跨模块复用;如果你用 @app.task,必须确保 app 是从 myproject.celery 导入的,否则会创建多个独立实例,任务发不出去。
最容易被忽略的一点:Django 的数据库连接在 worker 进程中默认不自动启用。如果 task 里要查 ORM,必须手动触发 Django setup,或确保 os.environ.setdefault('DJANGO_SETTINGS_MODULE', ...) 已在 celery.py 中执行——这也是为什么 celery.py 放错位置会导致 ORM 报 AppRegistryNotReady。

















