允许Celery.py时的警告提示
PeriodicTask.last_run_at received a naive datetime (2024-05-19 06:33:20.983919) while time zone support is active.
警告原因:
问题出在Django的时区支持是活动的(ACTIVE),但是收到的是一个"naive"(不含时区信息)的日期时间对象。
在Django中,对于日期时间的处理,它区分为"aware"(包含时区信息)和"naive"(不包含时区信息)两种日期时间对象。
代码调整
你可以在Django的设置文件settings.py
中设置使用的时区TIME_ZONE
以及是否开启时区支持USE_TZ
。例如:
TIME_ZONE = 'UTC'
USE_TZ = True
在Django-Celery中,所有的日期时间信息应为"aware"对象。
所以,一种处理方式是确保你创建的所有Datetime对象都是aware的。在创建Datetime对象的时候,最好利用Django提供的timezone模块,而不是直接用Python的datetime模块。像下面这样:
from django.utils import timezone
current_time = timezone.now()
上述方法创建的current_time就是一个aware的日期时间对象。
如果你在Celery中定义的定时任务是用的Python的datetime模块创建的naive的日期时间对象,你需要修改为Django的timezone模块来创建。
如果你在Django的配置中已经设置了 USE_TZ = True
,那么在你的celery.py文件中,请确保你有以下这行代码:
from django.conf import settings
app.conf.enable_utc = settings.USE_TZ
这样可以确保Celery会使用和Django相同的设置来处理时区问题。
如果你有任务计划CELERY_BEAT_SCHEDULE
在你的celery.py
文件里,那么你可以使用Django设置的时区。celery.schedule.crontab
和celery.schedule.timedelta
是用来设置定时任务的,分别用于定时执行和周期执行的任务。
from datetime import timedelta
from celery.schedules import crontab
from django.utils import timezone
app.conf.beat_schedule = {
'task1': {
'task': 'your_project.tasks.your_task1',
'schedule': crontab(minute=0, hour='2,6', day_of_week='1', nowfun=timezone.now),
},
'task2': {
'task': 'your_project.tasks.your_task2',
'schedule': timedelta(hours=1),
},
}
在 schedule': crontab(minute=0, hour='2,6', day_of_week='1', nowfun=timezone.now),
中nowfun=timezone.now
保证了任务会根据Django的时区设置来执行。如果day_of_week='1'
,那么这个任务会在每周一的第2和第6个小时开始。
'schedule': timedelta(hours=1)
配置表示您的任务将每隔1小时运行一次。
需要注意的是,task的路径应该是从你的项目名称开始的全路径,就像从你的测试文件开始的那样。另外,请确保你已经在你的__init__.py
中导入了celery.py
来启动你的celery worker 和 celery beat。