我在服务器时间现在为 BST 的服务器中使用celery,突然我的计划任务在一个小时前执行! 以前,服务器时间是欧洲/伦敦,这是格林尼治标准时间,但是现在由于夏时制而变成了BST(格林尼治标准时间+ 1)
我已将celery配置为使用时区,例如:
CELERY_TIMEZONE = 'Europe/London'
然后,在调用任务时,我还将
eta
参数的值本地化为“Europe/London”,如下所示:from datetime import datetime
from pytz import timezone
locale_to_use = timezone('Europe/London')
current_time = locale_to_use.localize(datetime.now())
并在调用task时将此
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似乎在我的服务器时间正确地安排了任务。 最佳答案
您可能会发现将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允许您通过指定
eta
参数来推迟函数调用的执行。 eta
是一个datetime
对象,表示您希望何时运行该函数。 CELERY_TIMEZONE
指定用于eta
的日期时间的时区。因此,如果我们设置CELERY_TIMEZONE = 'America/New_York'
,则所有eta
参数都将被解释为代表纽约时间。更好的方法是设置
CELERY_TIMEZONE = 'UTC'
,并传递代表UTC时间戳的datetime对象。这避免了许多由于夏令时引起的问题。可用更多信息in the docs
编辑,
请参阅asksol关于注释中eta参数的构造方式的澄清和更正。
关于python - Celery时区的预定任务问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22786748/