定期的なタスク—Pythonドキュメント

提供:Dev Guides
Celery/docs/latest/userguide/periodic-tasks
移動先:案内検索

定期的なタスク

序章

セロリビートはスケジューラーです。 定期的にタスクを開始し、クラスター内の使用可能なワーカーノードによって実行されます。

デフォルトでは、エントリは:setting: `beat_schedule` 設定から取得されますが、SQLデータベースにエントリを格納するなど、カスタムストアを使用することもできます。

スケジュールに対して一度に1つのスケジューラーのみが実行されていることを確認する必要があります。そうしないと、タスクが重複してしまいます。 一元化されたアプローチを使用することは、スケジュールを同期する必要がなく、サービスがロックを使用せずに動作できることを意味します。


時間帯

定期的なタスクスケジュールはデフォルトでUTCタイムゾーンを使用しますが、:setting: `timezone` 設定を使用して使用するタイムゾーンを変更できます。

タイムゾーンの例は、 Europe / London です。

timezone = 'Europe/London'

この設定は、(app.conf.timezone = 'Europe/London')を使用して直接構成するか、app.config_from_objectを使用して構成した場合は構成モジュールに追加することにより、アプリに追加する必要があります。 構成オプションの詳細については、構成を参照してください。

デフォルトのスケジューラー(celerybeat-scheduleファイルにスケジュールを保存する)は、タイムゾーンが変更されたことを自動的に検出するため、スケジュール自体をリセットしますが、他のスケジューラー(Djangoデータベーススケジューラーなど)はそれほど賢くない場合があります。 、以下を参照)。その場合、スケジュールを手動でリセットする必要があります。

Djangoユーザー

Celeryは、Django1.4で導入された新しいUSE_TZ設定を推奨し、互換性があります。

Djangoユーザーの場合、TIME_ZONE設定で指定されたタイムゾーンが使用されます。または、:setting: `timezone` 設定を使用して、Celeryのみのカスタムタイムゾーンを指定できます。

タイムゾーン関連の設定が変更されてもデータベーススケジューラはリセットされないため、これを手動で行う必要があります。

$ python manage.py shell
>>> from djcelery.models import PeriodicTask
>>> PeriodicTask.objects.update(last_run_at=None)

Django-CeleryはCelery4.0以下のみをサポートします。Celery4.0以降の場合は、次のようにします。

$ python manage.py shell
>>> from django_celery_beat.models import PeriodicTask
>>> PeriodicTask.objects.update(last_run_at=None)

エントリー

タスクを定期的に呼び出すには、ビートスケジュールリストにエントリを追加する必要があります。

from celery import Celery
from celery.schedules import crontab

app = Celery()

@app.on_after_configure.connect
def setup_periodic_tasks(sender, **kwargs):
    # Calls test('hello') every 10 seconds.
    sender.add_periodic_task(10.0, test.s('hello'), name='add every 10')

    # Calls test('world') every 30 seconds
    sender.add_periodic_task(30.0, test.s('world'), expires=10)

    # Executes every Monday morning at 7:30 a.m.
    sender.add_periodic_task(
        crontab(hour=7, minute=30, day_of_week=1),
        test.s('Happy Mondays!'),
    )

@app.task
def test(arg):
    print(arg)

@app.task
def add(x, y):
    z = x + y
    print(z)

@on_after_configureハンドラー内からこれらを設定すると、test.s()を使用するときにモジュールレベルでアプリを評価しなくなります。 @on_after_configureはアプリのセットアップ後に送信されるため、アプリが宣言されているモジュールの外部のタスク(例: celery.Celery.autodiscover_tasks()によって配置された tasks.py ファイルでは、@on_after_finalizeなどの後のシグナルを使用する必要があります。

@add_periodic_task()関数は、バックグラウンドで:setting: `beat_schedule` 設定にエントリを追加します。同じ設定を使用して、定期的なタスクを手動で設定することもできます。

例: tasks.add タスクを30秒ごとに実行します。

app.conf.beat_schedule = {
    'add-every-30-seconds': {
        'task': 'tasks.add',
        'schedule': 30.0,
        'args': (16, 16)
    },
}
app.conf.timezone = 'UTC'

ノート

これらの設定をどこに置くべきか疑問に思っている場合は、構成を参照してください。 これらのオプションはアプリで直接設定することも、構成用に別のモジュールを保持することもできます。

args に単一アイテムのタプルを使用する場合は、コンストラクターが括弧のペアではなく、コンマであることを忘れないでください。


スケジュールにtimedeltaを使用すると、タスクは30秒間隔で送信されます(最初のタスクはセロリビートの開始後30秒ごとに送信され、最後の実行後30秒ごとに送信されます) )。

Crontabのようなスケジュールも存在します。 Crontabスケジュールのセクションを参照してください。

cron と同様に、最初のタスクが次のタスクの前に完了しない場合、タスクが重複する可能性があります。 それが懸念される場合は、ロック戦略を使用して、一度に1つのインスタンスのみを実行できるようにする必要があります(たとえば、タスクが一度に1つだけ実行されるようにするを参照)。

利用可能なフィールド

  • タスク

    実行するタスクの名前。

  • スケジュール

    実行の頻度。

    これは、整数、timedelta、またはcrontabとしての秒数にすることができます。 scheduleのインターフェースを拡張することにより、独自のカスタムスケジュールタイプを定義することもできます。

  • args

    位置引数(listまたはtuple)。

  • kwargs

    キーワード引数(dict)。

  • オプション

    実行オプション(dict)。

    これは、apply_async() – exchange 、 routing_key 、 expires などでサポートされている任意の引数にすることができます。

  • 相対的

    related がtrueの場合、timedeltaスケジュールは「クロックによって」スケジュールされます。 これは、timedeltaの期間に応じて、頻度が最も近い秒、分、時間、または日に丸められることを意味します。

    デフォルトでは、 related はfalseであり、頻度は丸められず、セロリビートが開始された時間に相対的です。


Crontabのスケジュール

特定の時刻や曜日など、タスクの実行時期をより細かく制御したい場合は、crontabスケジュールタイプを使用できます。

from celery.schedules import crontab

app.conf.beat_schedule = {
    # Executes every Monday morning at 7:30 a.m.
    'add-every-monday-morning': {
        'task': 'tasks.add',
        'schedule': crontab(hour=7, minute=30, day_of_week=1),
        'args': (16, 16),
    },
}

これらのCrontab式の構文は非常に柔軟です。

いくつかの例:

意味
crontab() 毎分実行します。
crontab(minute=0, hour=0) 毎日深夜に実行します。
crontab(minute=0, hour='*/3') 3時間ごとに実行します:深夜、午前3時、午前6時、午前9時、正午、午後3時、午後6時、午後9時。
crontab(minute=0,
hour='0,3,6,9,12,15,18,21')
前と同じ。
crontab(minute='*/15') 15分ごとに実行します。
crontab(day_of_week='sunday') 日曜日に毎分(!)実行します。
crontab(minute='*',
hour='*', day_of_week='sun')
前と同じ。
crontab(minute='*/10',
hour='3,17,22', day_of_week='thu,fri')
10分ごとに実行しますが、木曜日または金曜日の午前3時から4時、午後5時から6時、および午後10時から11時の間のみ実行してください。
crontab(minute=0, hour='*/2,*/3') 偶数時間ごとに実行し、1時間ごとに3で割り切れます。 つまり、1時間ごとにを除く:午前1時、午前5時、午前7時、午前11時、午後1時、午後5時、午後7時、午後11時
crontab(minute=0, hour='*/5') 5で割り切れる時間を実行します。 これは、午後5時ではなく午後3時にトリガーされることを意味します(午後3時は24時間制の値「15」に等しいため、5で割り切れます)。
crontab(minute=0, hour='*/3,8-17') 3で割り切れる時間ごと、および営業時間中(午前8時から午後5時)は1時間ごとに実行します。
crontab(0, 0, day_of_month='2') 毎月2日に実行します。
crontab(0, 0,
day_of_month='2-30/2')
偶数日ごとに実行します。
crontab(0, 0,
day_of_month='1-7,15-21')
月の第1週と第3週に実行します。
crontab(0, 0, day_of_month='11',
month_of_year='5')
毎年5月11日に実行します。
crontab(0, 0,
month_of_year='*/3')
四半期ごとの最初の月に毎日実行します。

詳細については、celery.schedules.crontabを参照してください。


ソーラースケジュール

日の出、日の入り、夜明け、または夕暮れに応じて実行する必要があるタスクがある場合は、solarスケジュールタイプを使用できます。

from celery.schedules import solar

app.conf.beat_schedule = {
    # Executes at sunset in Melbourne
    'add-at-melbourne-sunset': {
        'task': 'tasks.add',
        'schedule': solar('sunset', -37.81753, 144.96715),
        'args': (16, 16),
    },
}

引数は単純です:solar(event, latitude, longitude)

緯度と経度には必ず正しい記号を使用してください。

サイン 口論 意味
+ latitude
- latitude
+ longitude
- longitude 西

可能なイベントタイプは次のとおりです。

イベント 意味
dawn_astronomical 空が完全に暗くならない瞬間に実行します。 これは、太陽が地平線から18度下にあるときです。
dawn_nautical 地平線といくつかのオブジェクトを区別するのに十分な日光があるときに実行します。 正式には、太陽が地平線から12度下にあるとき。
dawn_civil 野外活動を開始できるように、オブジェクトを区別できる十分な光があるときに実行します。 正式には、太陽が地平線から6度下にあるとき。
sunrise 朝、太陽の上端が東の地平線上に現れたときに実行します。
solar_noon その日の太陽が地平線より上にあるときに実行します。
sunset 夕方、太陽の後縁が西の地平線上に消えたときに実行します。
dusk_civil オブジェクトがまだ識別可能で、いくつかの星や惑星が見えるとき、市民の夕暮れの終わりに実行します。 正式には、太陽が地平線から6度下にあるとき。
dusk_nautical 太陽が地平線から12度下にあるときに実行します。 オブジェクトは識別できなくなり、地平線は肉眼では見えなくなります。
dusk_astronomical 空が完全に暗くなる瞬間に実行します。 正式には、太陽が地平線から18度下にあるとき。

すべてのソーラーイベントはUTCを使用して計算されるため、タイムゾーン設定の影響を受けません。

極地では、太陽が毎日昇ったり沈んだりしない場合があります。 スケジューラーはこれらのケースを処理できます(つまり、sunriseイベントは、太陽が昇らない日には実行されません)。 唯一の例外はsolar_noonです。これは、太陽が天の子午線を通過する瞬間として正式に定義され、太陽が地平線の下にある場合でも毎日発生します。

トワイライトは、夜明けから日の出までの期間として定義されます。 そして日没と夕暮れの間。 上記のリストから適切なイベントを使用して、トワイライトの定義(市民、航海、または天文学)、およびトワイライトの開始時と終了時のどちらでイベントを実行するかに応じて、「トワイライト」に従ってイベントをスケジュールできます。 。

詳細については、celery.schedules.solarを参照してください。


スケジューラーの開始

セロリビートサービスを開始するには:

$ celery -A proj beat

ワーカー-Bオプションを有効にすることで、ワーカー内に beat を埋め込むこともできます。これは、複数のワーカーノードを実行しない場合に便利ですが、一般的には使用されないためです。本番環境での使用はお勧めしません:

$ celery -A proj worker -B

Beatは、タスクの最終実行時間をローカルデータベースファイル(デフォルトでは celerybeat-schedule という名前)に保存する必要があるため、現在のディレクトリに書き込むためのアクセス権が必要です。または、カスタムの場所を指定することもできます。このファイルの場合:

$ celery -A proj beat -s /home/celery/var/run/celerybeat-schedule

ノート

ビートをデーモン化するには、デーモン化を参照してください。


カスタムスケジューラクラスの使用

カスタムスケジューラクラスは、コマンドラインで指定できます(--scheduler引数)。

デフォルトのスケジューラーはcelery.beat.PersistentSchedulerで、ローカルのshelveデータベースファイルで最後の実行時間を追跡するだけです。

スケジュールをDjangoデータベースに保存し、実行時に定期的なタスクを管理するための便利な管理インターフェイスを提供する:pypi: `django-celery-beat` 拡張機能もあります。

この拡張機能をインストールして使用するには:

  1. pip を使用して、パッケージをインストールします。

    $ pip install django-celery-beat
  2. django_celery_beatモジュールをDjangoプロジェクトのsettings.pyINSTALLED_APPSに追加します。

    INSTALLED_APPS = (
        ...,
        'django_celery_beat',
    )

    モジュール名にはダッシュはなく、アンダースコアのみであることに注意してください。

  3. 必要なテーブルが作成されるように、Djangoデータベースの移行を適用します。

    $ python manage.py migrate
  4. django_celery_beat.schedulers:DatabaseSchedulerスケジューラーを使用して、セロリビートサービスを開始します。

    $ celery -A proj beat -l INFO --scheduler django_celery_beat.schedulers:DatabaseScheduler

    注:これを:setting: `beat_scheduler` 設定として直接追加することもできます。

  5. Django-Adminインターフェースにアクセスして、定期的なタスクを設定します。