我正在使用芹菜来安排一些任务。我可以使用CELERY_TIMEZONE设置来使用crontab计划安排任务,并在上述时区的预定时间运行。
但我希望能够在同一个应用程序中为不同的时区设置多个此类任务(单个django settings.py)。我知道在安排任务时需要在哪个时区运行哪个任务。
是否可以为每个任务指定不同的时区?
我正在使用django(1.4)和芹菜(3.0.11)以及django芹菜(3.0.11)。
我查看了djcelery.schedulers.DatabaseScheduler
类及其基类,但我无法弄清楚时区的使用方式和位置。我可以编写一个自定义调度程序,使每个作业可以在不同的时区运行吗?
谢谢,
答案 0 :(得分:10)
您可以在芹菜计划中实现单个任务的时区感知计划。这样,您可以通过为每个芹菜时间表指定一个单独的现在功能,根据特定时区的当地时间(也可以调整为夏令时)来运行任务
crontab
支持nowfun
argument指定用于检查是否应该运行的日期时间函数
import datetime
import pytz
nowfun = lambda: datetime.datetime.now(pytz.timezone('Europe/Berlin'))
在您的日程安排中,通过
将此功能设置为日期时间功能'periodic_task': {
'task': 'api.tasks.periodic',
'schedule': crontab(hour=6, minute=30, nowfun=nowfun)
}
每天早上6点30分CET调整为夏令时。
如果您多次使用该功能,请考虑创建帮助
from functools import partial
cet_crontab = partial(crontab, nowfun=nowfun)
'periodic_task': {
'task': 'api.tasks.periodic',
'schedule': cet_crontab(hour=6, minute=30)
}
确保您设置了CELERY_ENABLE_UTC = False
,否则芹菜会将您的日程安排转换为UTC。
答案 1 :(得分:1)
我认为最简单的方法是使用装饰器mock
from mock import patch
@task
@patch.multiple(settings, CELERY_TIMEZONE='time_zone')
def my_task(*args):
#do your staff
我还没有测试过,但似乎没错。我希望我能帮到你:)。
答案 2 :(得分:0)
也许我误解了这个问题,但是如果你想在不同时区的某个时间运行任务,你能不能只按时区之间的小时差来调整预定时间?例如,如果我希望任务在下午5点在两个不同的TZ中运行:
# settings.py
CELERY_TIMEZONE = "US/Eastern"
CELERYBEAT_SCHEDULE = {
# Task to run in EST
'schedule-my-est-task': {
'task': 'path.to.my.est.task',
'schedule': crontab(minute=0, hour=17),
},
# Task to run in UTC - hour time is offset
'schedule-my-utc-task': {
'task': 'path.to.my.utc.task',
'schedule': crontab(minute=0, hour=10),
},
}
答案 3 :(得分:0)
就我而言,我需要一个函数,该函数每次都会运行,并从db中获取特定值的时区。
我创建了一个新函数,该函数将接受一个变量并为我提供所需的时区。
def get_time(db_query: str) -> datetime.datetime:
"""Extract timezone from DB"""
# get location from db
timezone = 'get timezone for location'
# return calculated datetime using timezone
return datetime.datetime.now(pytz.timezone(timezone))
def custom_crontab(*args, **kwargs):
"""Create a custom crontab that will call get_time function and assign value to nowfun"""
db_query = kwargs.pop("db_query")
nowfun = get_time(db_query)
kwargs['nowfun'] = nowfun
# return the call to crontab
return crontab(*args, **kwargs)
beat_schedule = {
'periodic_task': {
'task': 'main_job',
'schedule': custom_crontab(minute=0, db_query='some_value'),
}
}