【问题标题】:Celery beat: Change to individual timezone tasks causing validation error "Invalid timezone"Celery beat:更改为单个时区任务导致验证错误“无效时区”
【发布时间】:2021-10-29 08:30:20
【问题描述】:

芹菜--版本 5.1.2(太阳谐波)

django --version 3.2.8

我有一个 celery 时间表,其中包含在不同时区运行的四个任务。我正在使用 nowfun 设置时区,并在 settings.py 中设置了 CELERY_ENABLE_UTC = False。我关注了这篇 SO 帖子的最高回复:Celery beat - different time zone per task

请注意,我今天早上进行了此更改 - 我运行的是没有这些设置的早期版本的代码。

目前,我将芹菜结果保存到 CELERY_RESULT_BACKEND = 'django-db'。

由于实施了允许根据不同时区运行不同任务的更改,因此在运行 celery -A backend beat -l info 时出现错误。

虽然这里是头部和尾部,但它非常长: 头:

[2021-10-29 07:29:36,059:INFO/MainProcess] 节拍:开始... [2021-10-29 07:29:36,067:错误/MainProcess] 无法添加条目 'celery.backend_cleanup' 到数据库计划: ValidationError(["无效时区 ''"])。 内容:{'task': 'celery.backend_cleanup', 'schedule':

      • (m/h/d/dM/MY)>, 'options': {'expire_seconds': 43200}}

尾巴:

django.core.exceptions.ValidationError: ["时区无效 ''"]

Celery beat 挂在最后一条错误消息上,我必须用 ctrl + c 杀死它。

我在 celery 上阅读了他们关于在时区相关设置更改时手动重置数据库的说明 - 网站说:

$ python manage.py shell

从 django_celery_beat.models 导入

PeriodicTask PeriodicTask.objects.update(last_run_at=None)

然后我找到了一些documentation 说:

警告:如果您更改 Django TIME_ZONE 设置您的周期性任务 时间表仍将基于旧时区。解决这个问题 必须为每个周期性任务重置“上次运行时间”:

从 django_celery_beat.models 导入 PeriodicTask, PeriodicTasks

PeriodicTask.objects.all().update(last_run_at=None)

PeriodicTasks.changed()

请注意,这将重置状态,就好像周期性任务从未运行过一样。

所以我认为导致问题的原因正是上面所说的 - 我更改了时区,并且时间表仍在旧的 UTC 时区运行,所以我需要更新它,尽管我的时间表之前已经运行过,所以当我输入时:

>>> PeriodicTask.objects.all().update(last_run_at=None)

我收到回复:

13

然后当我进入时:

>>> PeriodicTasks.changed()

我收到一个类型错误:

TypeError: changed() 缺少 1 个必需的位置参数: '实例'

所以我的问题是:

如何更新 PeriodTask 和 PeriodicTasks?我应该将什么参数传递给 PeriodicTasks.changed() 以及 13 是第一个命令的预期响应吗?

这是我的 celery.py:

from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
from django.conf import settings
from celery.schedules import crontab
import pytz
from datetime import datetime

os.environ.setdefault(
    'DJANGO_SETTINGS_MODULE',
    'backend.settings'
)

app = Celery(
    'backend'
)

app.config_from_object(
    settings,
    namespace='CELERY'
)

def uk_time():
     return datetime.now(pytz.timezone('Europe/London'))

def us_time():
    return datetime.now(pytz.timezone('EST'))

def jp_time():
    return datetime.now(pytz.timezone('Japan'))

# Celery Beat Settings
app.conf.beat_schedule={
    'generate_signals_london': {
        'task': 'signals.tasks.generate_signals',
        'schedule': crontab(
            minute=0,
            hour=8,
            nowfun=uk_time,
            day_of_week='1,2,3,4,5'
        ),
        'args': ('UK',),
    },

    'generate_signals_ny': {
        'task': 'signals.tasks.generate_signals',
        'schedule': crontab(
            minute=0,
            hour=7,
            nowfun=us_time,
            day_of_week='1,2,3,4,5'
        ),
        'args': ('NY',),
    },

    'generate_signals_nyse': {
        'task': 'signals.tasks.generate_signals',
        'schedule': crontab(
            minute=0,
            hour=9,
            nowfun=us_time,
            day_of_week='1,2,3,4,5'
        ),
        'args': ('NYSE',),
    },

    'generate_signals_asia': {
        'task': 'signals.tasks.generate_signals',
        'schedule': crontab(
            minute=0,
            hour=8,
            nowfun=jp_time,
            day_of_week='1,2,3,4,5'
        ),
        'args': ('JP',),
    },

}

app.autodiscover_tasks()

【问题讨论】:

    标签: django timezone celery django-celery celerybeat


    【解决方案1】:

    有时当我们试图解决一个问题时,我们实际上是在解决一个由解决初始问题的不正确方法所产生的问题。

    如果答案是“这就是您在更改时区时更新 PeriodicTask、先前运行任务的 PeriodicTasks 的方式”,那么最初的问题是什么?

    这里的原始问题是更改不同任务的时区,以便这些任务包含不同时区的 DST。遵循Celery beat - different time zone per task 上的解决方案并不是解决此问题的最有效方法。

    为避免需要更新 PeriodicTask 和 PeriodicTasks 不要更改 CELERY_ENABLE_UTC = False 而是按照这篇文章的答案以 UTC 运行所有内容:Celery scheduled tasks problems with Timezone

    这解决了原来的问题。

    这是我更新的 celery.py 和一个可行的解决方案:

    from __future__ import absolute_import, unicode_literals
    import os
    from celery import Celery
    from django.conf import settings
    from celery.schedules import crontab
    import pytz
    from datetime import datetime
    
    os.environ.setdefault(
        'DJANGO_SETTINGS_MODULE',
        'backend.settings'
    )
    
    app = Celery(
        'backend'
    )
    
    app.config_from_object(
        settings,
        namespace='CELERY'
    )
    
    dt = datetime.now()
    tz = pytz.timezone('Europe/London')
    dst = tz.localize(dt)
    
    if bool(dst.dst()):
        uk_market_open = 9
    else:
        uk_market_open = 8
    
    tz = pytz.timezone('US/Eastern')
    dst = tz.localize(dt)
    
    if bool(dst.dst()):
        ny_market_open = 12
        nyse_market_open = 14
    else:
        ny_market_open = 13
        nyse_market_open = 15
    
    jp_market_open = 23
    
    # Celery Beat Settings
    app.conf.beat_schedule={
        'generate_signals_london': {
            'task': 'signals.tasks.generate_signals',
            'schedule': crontab(
                minute=0,
                hour=uk_market_open,
                day_of_week='1,2,3,4,5'
            ),
            'args': ('UK',),
        },
    
        'generate_signals_ny': {
            'task': 'signals.tasks.generate_signals',
            'schedule': crontab(
                minute=0,
                hour=ny_market_open,
                day_of_week='1,2,3,4,5'
            ),
            'args': ('NY',),
        },
    
        'generate_signals_nyse': {
            'task': 'signals.tasks.generate_signals',
            'schedule': crontab(
                minute=0,
                hour=nyse_market_open,
                day_of_week='1,2,3,4,5'
            ),
            'args': ('NYSE',),
        },
    
        'generate_signals_asia': {
            'task': 'signals.tasks.generate_signals',
            'schedule': crontab(
                minute=0,
                hour=jp_market_open,
                day_of_week='1,2,3,4,5'
            ),
            'args': ('JP',),
        },
    
    }
    
    app.autodiscover_tasks()
    

    【讨论】:

      猜你喜欢
      • 2015-10-24
      • 2013-11-10
      • 1970-01-01
      • 1970-01-01
      • 2021-02-25
      • 2019-07-20
      • 2019-02-16
      • 2017-05-11
      • 1970-01-01
      相关资源
      最近更新 更多