Celery预定了Timezone的任务问题

时间:2014-04-01 13:03:12

标签: python celery

我在服务器时间现在 BST 的服务器中使用芹菜,突然我的计划任务正在执行一小时!以前,服务器时间是欧洲/伦敦是格林威治标准时间,但现在由于节省了一天,它已成为BST(GMT + 1)

我已将芹菜配置为使用时区,如:

CELERY_TIMEZONE = 'Europe/London'

然后,在调用任务时,我还将eta参数的本地化值定义为“欧洲/伦敦'像这样:

from datetime import datetime
from pytz import timezone

locale_to_use = timezone('Europe/London')
current_time = locale_to_use.localize(datetime.now())

在调用任务时使用此current_time作为eta参数的值。

现在我是否有任何错误,就像本地化eta参数值一样?我的服务器在BST。

在白天节能时区生效之前,这个配置没有出现任何问题!

修改

为了清楚说明,我在这里发布了我的代码示例:

@app.task(ignore_result=True)
def eta_test():

    logger.info('Executing eta_test on {0}'.format(datetime.now()))


def run_eta_test(hour, minute):

    now_time = datetime.now()
    target_time = now_time.replace(hour=hour, minute=minute, second=0)

    from settings import options
    from pytz import timezone

    local_zone = timezone('Europe/London')

    target_time = local_zone.localize(target_time)

    eta_test.apply_async(eta=target_time)

然后我从服务器的python控制台调用run_eta_test,如下所示:

test_tasks.run_eta_test(17, 17)

即,在同一天的17:17:00执行任务。服务器时间是17:15:45而不是在2秒后安排它,它立即执行任务:

[2014-04-04 17:15:45,341: INFO/MainProcess] Received task: scheduling.test_tasks.eta_test[c28448d6-3a51-42f7-9df2-cb93385ff7c6] eta:[2014-04-04 17:17:00.095001+01:00]
[2014-04-04 17:15:46,820: INFO/Worker-3] Executing eta_test on 2014-04-04 17:15:46.820316
[2014-04-04 17:15:46,820: INFO/MainProcess] Task scheduling.test_tasks.eta_test[c28448d6-3a51-42f7-9df2-cb93385ff7c6] succeeded in 0.0008487419690936804s: None

然后我再次调用该任务,在1小时几秒后执行,调用如下:

test_tasks.run_eta_test(18, 17)

而不是将其安排到一小时几秒之后,该任务仅在几秒钟之后执行,即一小时之前:

[2014-04-04 17:16:27,703: INFO/MainProcess] Received task: scheduling.test_tasks.eta_test[f1a54d08-c12d-457f-bee8-04ca35b32242] eta:[2014-04-04 18:17:00.700327+01:00]
[2014-04-04 17:17:01,846: INFO/Worker-2] Executing eta_test on 2014-04-04 17:17:01.846561
[2014-04-04 17:17:01,847: INFO/MainProcess] Task scheduling.test_tasks.eta_test[f1a54d08-c12d-457f-bee8-04ca35b32242] succeeded in 0.0012819559779018164s: None

我的服务器日期配置为BST,如:

Fri Apr  4 17:29:10 BST 2014

现在,服务器中的时区是个问题吗?

再次编辑:

我无法在答案和评论的帮助下解决问题。所以我所做的是,使用:CELERY_ENABLE_UTC = False并且根本不使用CELERY_ENABLE_UTC的任何值。然后,我使用我的服务器时间没有任何本地化。 Celery似乎在我的服务器时间正确安排任务。

3 个答案:

答案 0 :(得分:10)

您可能会发现将CELERY_TIMEZONE设置为'UTC'会更容易。然后,如果要使用“本地时间”来安排事件,可以执行以下操作:

london_tz = pytz.timezone('Europe/London')
london_dt = london_tz.localize(datetime.datetime(year, month, day, hour, min))
give_this_to_celery = london_dt.astimezone(pytz.UTC)

不可否认,这是更多的工作。本地化日期时间,然后转换它并获得一个天真的日期时间。但是,它应该解决使用时区的大多数麻烦。

编辑:你问,

  

你能告诉我CELERY_TIMEZONE究竟是做什么的吗?芹菜如何使用eta值来计算倒计时?

Celery允许您通过指定eta参数来推迟执行函数调用。 eta是一个datetime对象,表示您希望运行该函数的时间。 CELERY_TIMEZONE指定eta使用的日期时间的时区。因此,如果我们设置CELERY_TIMEZONE = 'America/New_York',我们所有的eta参数都会被解释为它们代表纽约时间。

最好设置CELERY_TIMEZONE = 'UTC',并传递表示UTC时间戳的datetime对象。这避免了夏令时造成的很多问题。

提供更多信息in the docs

编辑,

请参阅asksol关于如何在评论中构建eta参数的澄清和更正。

答案 1 :(得分:1)

这是Celery 4中的一个错误,我曾帮助在Celery 4.2中进行了修复-确实,解决方法是将芹菜项目的时区设置为UTC,但是从Celery 4.2开始,您可以使用任何您再次想要的时区和celerybeat计划将正常工作。原始错误报告/ PR中的更多详细信息:https://github.com/celery/celery/pull/4324

答案 2 :(得分:0)

我觉得很奇怪,如果我们设置celery_time区域,它会通过将当地时间添加到utc来调整eta时间。 但是,芹菜eta时钟似乎是在utc时间触发的。 现在utc时间是时间+芹菜时区,这是错误的。

我猜@bgschiller使用utc作为默认时区是一种解决这个问题的方法..

def celery_localtime_util(t):
    bj_tz = pytz.timezone('*')
    bj_dt = bj_tz.localize(t)
    return bj_dt.astimezone(pytz.UTC)

使用这个作品......