スケジュールされたジョブを設定しますか?


519

私はDjangoを使用してWebアプリで作業しており、ジョブを定期的に実行するようにスケジュールする方法があるかどうか知りたいです。

基本的には、データベースを実行して、自動的に定期的にいくつかの計算/更新を行いたいのですが、これを行うためのドキュメントが見つからないようです。

誰でもこれを設定する方法を知っていますか?

明確にするためcronに、私はこれを実行するジョブを設定できることを知っていますが、この機能を提供するDjangoの機能があるかどうか知りたいです。多くの設定(できればゼロ)を行わなくても、このアプリを自分でデプロイできるようにしたいと思います。

最後にリクエストがサイトに送信されてからジョブが実行されているかどうかを確認するだけで、これらのアクションを「遡及的に」トリガーすることを検討しましたが、もう少しクリーンなものを望んでいます。


1
あなたが高パフォーマンスのサイトですでにRabbitMQを使用している場合、ここにcronを回避するコツがあります。AMQPを使用してcronのようなスケジューリングを行う
Van Gale

私が正しく理解している場合、Djangoでいくつかのタスクをスケジュールする必要があります。私が最近見つける最高のものはこれです:celery.github.com/celery/index.html
Ali Nikneshan

これについてどう思いますか?github.com/reavis/django-cron
Domenico Monaco

ティックは、このすべての作業を回避するためだけのものです。【免責事項】チェックを入れます。
Siscia 2014年

2
github.com/coleifer/huey Hueyはここで言及する必要があります。Djangoでのセットアップは途方もなく簡単です。
Brandon Bertelsen、2018

回答:


363

私が採用した1つの解決策は、これを行うことです。

1)を作成したカスタム管理コマンドを、例えば

python manage.py my_cool_command

2)cron(Linuxの場合)またはat(Windowsの場合)を使用して、必要なときにコマンドを実行します。

これは、重いAMQPスタックをインストールする必要がない単純なソリューションです。ただし、他の回答で言及されているセロリのようなものを使用することには、優れた利点があります。特に、Celeryを使用すると、アプリケーションロジックをcrontabファイルに分散する必要がないので便利です。ただし、cronソリューションは、小規模から中規模のアプリケーション、および多くの外部依存関係が必要ない場合に非常にうまく機能します。

編集:

新しいバージョンのWindowsでは、このatコマンドはWindows 8、Server 2012以降では非推奨です。schtasks.exe同じ用途に使用できます。

****更新****これは、カスタム管理コマンドを作成するためのdjango docの新しいリンクです


5
これは、外部サービスなしでこれを行う方法ですが、実行中のdjangoフレームワークプロセスのみを使用していますか?
sergzach

4
@Brian_Neal django_cronアプリケーション。
sergzach

2
毎月最終日にcronを使用して仮想環境で管理コマンドを実行する方法を教えてください。
mmrs151 2012年

2
@sergzachこのコメントをフォローアップしたところ、この名前のパッケージが2つあることがわかりました。Google Codeの上ジャンゴ-のcronのGithub上のジャンゴ- cronの。それらは少し異なりますが、どちらも興味深いものです。どちらも、「ジャンゴニック」な方法でcronを定義できます。最初のものは少し古く、外部タスク(つまりcron)なしで動作することを目指しています。一方、2番目の方法では、実行するcronを設定する必要があります。python manage.py runcronsこれにより、定義および登録したすべてのcronが実行されます。
ドリフトキャッチャー

1
@sergzach最初の1つである「django-cron on Google Code」を参照していると想定しています。あなたはそれについて正しいです。これが実際に私が2つ目の「django-cron on GitHub」を選択する理由です。これにより、シンプルなcrontabのセットアップ/管理-管理コマンドを参照するcrontabが1つだけになります。ただし、別のcrontabを使用しているためこの同期の問題を回避するcronプロセス(私が知る限り)。
ドリフトキャッチャー

152

Celeryは、AMQP(RabbitMQ)上に構築された分散タスクキューです。また、cronのような方法で定期的なタスクを処理します(定期的なタスクを参照)。アプリによっては、一見の価値があるかもしれません。

Celeryはdjango(docs)を使用して設定するのが非常に簡単で、定期的なタスクは、ダウンタイムの場合に実際に見逃したタスクをスキップします。Celeryには、タスクが失敗した場合に備えて、再試行メカニズムが組み込まれています。


51

私たちは構造化アプリであると私が考えるものをオープンソース化しました。上記のブライアンの解決策もほのめかしています。私たちはどんな/すべてのフィードバックも大好きです!

https://github.com/tivix/django-cron

1つの管理コマンドが付属しています。

./manage.py runcrons

それは仕事をします。各cronはクラスとしてモデル化されているため(そのすべてのOO)、各cronは異なる頻度で実行され、同じcronタイプが並行して実行されないようにしています(cron自体がその頻度よりも実行に時間がかかる場合に備えて!)


5
@chachra申し訳ありませんが、これは馬鹿げた質問かもしれませんが、これはWindowsでat機能するのcronでしょうか、それとも特別に機能するように設計されたのでしょうか。
Bruno Finger

38

標準のPOSIX OSを使用している場合は、cronを使用します。

Windowsを使用している場合は、で使用ます。

Django管理コマンドを

  1. 彼らが利用しているプラ​​ットフォームを把握する。

  2. ユーザーのために適切な「AT」コマンドを実行して、どちらかまたはユーザーのためのcrontabを更新します。


10
できれば、それを私のdjangoアプリに組み込んでもらいたいのですが。
TM。

@TM:「djangoアプリにロールアップ」とはどういう意味ですか?質問を明確にしてください。
S.Lott、2009

10
cronジョブを自分で設定する必要なく、このアプリを簡単にデプロイできるようにしてほしいです。
TM。

1
cronインターフェースは常にアプリにラップできます。
monkut 2009

BSD、Mac、およびUnixライクなOSにはcronがあります。
DylanYoung

23

興味深い新しいプラグイン可能なDjangoアプリ:django-chronograph

タイマーとして機能するcronエントリを1つ追加するだけで済み、実行するスクリプトに非常に優れたDjango管理インターフェイスがあります。


2
ジャンゴクロノグラフはメンテナンスされていません。フォークの方がはるかに良くなっています:github.com/chrisspen/django-chroniker
Menda

16

Django Poor Man's Cronは、スパムボット、検索エンジンのインデックス作成ロボットなどを利用して、スケジュールされたタスクをほぼ定期的に実行するDjangoアプリです。

参照:http : //code.google.com/p/django-poormanscron/


2
これは、DjangoアプリがWebからアクセス可能であることも前提としています。これは、LANやVPNでのデプロイの場合は当てはまりません。
TimH-Codidact 2017年

10

私は少し前にまったく同じ要件を持っていて、APSchedulerユーザーガイド)を使用してそれを解決することになりました

これにより、ジョブのスケジューリングが非常に簡単になり、一部のコードの要求ベースの実行から独立しています。以下は簡単な例です。

from apscheduler.schedulers.background import BackgroundScheduler

scheduler = BackgroundScheduler()
job = None

def tick():
    print('One tick!')\

def start_job():
    global job
    job = scheduler.add_job(tick, 'interval', seconds=3600)
    try:
        scheduler.start()
    except:
        pass

これが誰かに役立つことを願っています!


9

ブライアンニールのcronを介した管理コマンドの実行の提案はうまく機能しますが、もう少し堅牢なもの(ただし、セロリほど複雑ではありません)を探している場合は、クロノスのようなライブラリを調べます。

# app/cron.py

import kronos

@kronos.register('0 * * * *')
def task():
    pass

9

RabbitMQとCeleryには、Cronよりも多くの機能とタスク処理機能があります。タスクの失敗が問題ではなく、次の呼び出しで壊れたタスクを処理すると思われる場合は、Cronで十分です。

Celery&AMQPを使用すると、壊れたタスクを処理でき、タスクのmax_retries属性に到達するまで、別のワーカーによって再度実行されます(Celeryワーカーは、次に実行するタスクをリッスンします)。失敗をログに記録したり、max_retries到達したら管理者に電子メールを送信したりするなど、失敗時にタスクを呼び出すこともできます。

また、アプリケーションをスケーリングする必要がある場合は、CeleryサーバーとAMQPサーバーを配布できます。


8

個人的にはcronを使用していますが、django-extensionsのJobs Scheduling部分は面白そうです。


それでもトリガーはcronに依存し、その間に別の抽象化レイヤーを追加するだけです。個人的には、それだけの価値があるかどうかわかりません。
カールマイヤー

私は同意し、それについて考えた後、cronがとにかくうまく機能できるときに、リクエストミドルウェアが私のサイト(上記のpoormanscronを参照)の速度を低下させたくない。
ヴァンゲイル

7

Djangoの一部ではありませんが、Airflowはタスク管理に役立つ最新のプロジェクトです(2016年現在)。

Airflowは、データパイプラインの作成と管理に使用できるワークフロー自動化およびスケジューリングシステムです。WebベースのUIは、これらのパイプラインを管理および表示するためのさまざまなオプションを開発者に提供します。

AirflowはPythonで記述され、Flaskを使用して構築されています。

AirflowはAirbnbのMaxime Beaucheminによって作成され、2015年の春にオープンソース化されました。これは、2016年の冬にApache Software Foundationのインキュベーションプログラムに参加しました。Gitプロジェクトページと追加の背景情報があります。


6

cron.pyファイルの先頭に次を追加します。

#!/usr/bin/python
import os, sys
sys.path.append('/path/to/') # the parent directory of the project
sys.path.append('/path/to/project') # these lines only needed if not on path
os.environ['DJANGO_SETTINGS_MODULE'] = 'myproj.settings'

# imports and code below

6

私はこのかなり単純な解決策について考えました:

  1. 他のビューと同じように、ビュー関数do_work(req、param)を定義し、URLマッピングを使用して、HttpResponseを返します。
  2. curl http:// localhost / your / mapped / url?param = valueを実行するタイミング設定を使用して(またはWindowsではATまたはスケジュールされたタスクを使用して)cronジョブを設定します

パラメータを追加できますが、URLにパラメータを追加するだけです。

皆さんがどう思うか教えてください。

[更新] curlではなく、django-extensionsからrunjobコマンドを使用しています。

私のcronは次のようになります。

@hourly python /path/to/project/manage.py runjobs hourly

...など、毎日、毎月など」特定のジョブを実行するように設定することもできます。

私はそれがより扱いやすく、よりクリーンだと思います。URLをビューにマッピングする必要はありません。ジョブクラスとcrontabを定義するだけで準備は完了です。


1
検出している問題は、アプリと帯域幅に不必要に負荷を追加することであり、バックグラウンドジョブを実行するだけです。しかし、それ以外は、アプリのサーバーの外部にあるエージェントから呼び出すこともできるので、より一般的なdjango-cronです。
nemesisfixx 2012年

あなたが正しい、それが私がdjango-command-extensionsからのジョブの使用に移行した理由です。私の回答の更新をご覧ください。
Michael

4

コードの部分の後で、views.pyと同じように何でも書くことができます:)

#######################################
import os,sys
sys.path.append('/home/administrator/development/store')
os.environ['DJANGO_SETTINGS_MODULE']='store.settings'
from django.core.management impor setup_environ
from store import settings
setup_environ(settings)
#######################################

http://www.cotellese.net/2007/09/27/running-external-scripts-against-django-models/から


3

あなたは間違いなくdjango-qをチェックするべきです!追加の構成は必要なく、商業プロジェクトでの生産上の問題を処理するために必要なすべてのものを持っている可能性があります。

積極的に開発されており、django、django ORM、mongo、redisと非常によく統合されています。これが私の設定です:

# django-q
# -------------------------------------------------------------------------
# See: http://django-q.readthedocs.io/en/latest/configure.html
Q_CLUSTER = {
    # Match recommended settings from docs.
    'name': 'DjangoORM',
    'workers': 4,
    'queue_limit': 50,
    'bulk': 10,
    'orm': 'default',

# Custom Settings
# ---------------
# Limit the amount of successful tasks saved to Django.
'save_limit': 10000,

# See https://github.com/Koed00/django-q/issues/110.
'catch_up': False,

# Number of seconds a worker can spend on a task before it's terminated.
'timeout': 60 * 5,

# Number of seconds a broker will wait for a cluster to finish a task before presenting it again. This needs to be
# longer than `timeout`, otherwise the same task will be processed multiple times.
'retry': 60 * 6,

# Whether to force all async() calls to be run with sync=True (making them synchronous).
'sync': False,

# Redirect worker exceptions directly to Sentry error reporter.
'error_reporter': {
    'sentry': RAVEN_CONFIG,
},
}

3

Django APScheduler for Scheduler Jobs。高度なPythonスケジューラ(APScheduler)は、Pythonコードを後で1回だけまたは定期的に実行するようにスケジュールできるPythonライブラリです。新しい仕事を追加したり、古い仕事をその場で削除したりできます。

注:私はこのライブラリの作成者です

APSchedulerをインストールする

pip install apscheduler

呼び出すファイル関数を表示

ファイル名:scheduler_jobs.py

def FirstCronTest():
    print("")
    print("I am executed..!")

スケジューラーの構成

execute.pyファイルを作成し、以下のコードを追加します

from apscheduler.schedulers.background import BackgroundScheduler
scheduler = BackgroundScheduler()

作成した関数ここでは、スケジューラー関数はscheduler_jobsに記述されています。

import scheduler_jobs 

scheduler.add_job(scheduler_jobs.FirstCronTest, 'interval', seconds=10)
scheduler.start()

実行するファイルをリンクする

次に、URLファイルの下部に以下の行を追加します

import execute

2

今日、あなたの問題と似たようなことがありました。

私はそれをcronを介してサーバーで処理したくありませんでした(そして、ほとんどのlibは結局のところcronヘルパーにすぎませんでした)。

だから私はスケジューリングモジュールを作成し、それをinitにアタッチしました。

これは最善の方法ではありませんが、すべてのコードを1か所に配置し、その実行をメインアプリに関連付けておくと役立ちます。


2

はい、上記の方法はとても素晴らしいです。そして、私はそれらのいくつかを試しました。ついに、私はこのような方法を見つけました:

    from threading import Timer

    def sync():

        do something...

        sync_timer = Timer(self.interval, sync, ())
        sync_timer.start()

ちょうど再帰的です。

わかりました、私はこの方法があなたの要件を満たすことを望みます。:)


1
「何か」が失敗すると停止します。その中ですべての例外を処理するようにしてください。それでも、ある時点でWebサーバーがスレッドを強制終了する可能性がありますか?
Lutz Prechelt 2014年

2

より最新のソリューション(Celeryと比較して)はDjango Qです:https : //django-q.readthedocs.io/en/latest/index.html

すばらしいドキュメントがあり、簡単に読むことができます。Windowsはプロセス分岐をサポートしていないため、Windowsのサポートが欠けています。ただし、Windows for Linuxサブシステムを使用して開発環境を作成する場合は問題なく動作します。


Windowsのシングルクラスターモードでも引き続き使用できるようです
鷲尾

1

セロリを使って定期的なタスクを作成しています。まず、次のようにインストールする必要があります。

pip install django-celery

django-celery設定に登録することを忘れないでください、そうすれば次のようなことができます:

from celery import task
from celery.decorators import periodic_task
from celery.task.schedules import crontab
from celery.utils.log import get_task_logger
@periodic_task(run_every=crontab(minute="0", hour="23"))
def do_every_midnight():
 #your code

2
このアドバイスは時代遅れであり、セロリを直接統合できます。詳細については、pypi.python.org / pypi / django-celeryを参照してください。
Peter Brittain、2015

Celeryのドキュメントによると、これはv3.1での変更点です。私自身はまだ試していません。
Peter Brittain、2015

1

システムの他のユーザーに、実際のサーバー(Windows)タスクスケジューラへのアクセス権を与えることなく、ジョブをスケジュールする必要があったため、これが誰にとっても役に立つかどうかはわかりません。この再利用可能なアプリを作成しました。

ユーザーは、必要なコマンド/タスク/.batファイルを作成できるサーバー上の1つの共有フォルダーにアクセスできることに注意してください。このタスクは、このアプリを使用してスケジュールできます。

アプリ名はDjango_Windows_Schedulerです

スクリーンショット: ここに画像の説明を入力してください



0

単純なドッキングプロジェクトの場合、既存の回答の適合は実際には確認できませんでした。

そのため、外部ライブラリやトリガーを必要とせず、独自に実行する非常に基本的なソリューションを作成しました。外部os-cronは必要ありません。すべての環境で機能するはずです。

ミドルウェアを追加することで機能します。 middleware.py

import threading

def should_run(name, seconds_interval):
    from application.models import CronJob
    from django.utils.timezone import now

    try:
        c = CronJob.objects.get(name=name)
    except CronJob.DoesNotExist:
        CronJob(name=name, last_ran=now()).save()
        return True

    if (now() - c.last_ran).total_seconds() >= seconds_interval:
        c.last_ran = now()
        c.save()
        return True

    return False


class CronTask:
    def __init__(self, name, seconds_interval, function):
        self.name = name
        self.seconds_interval = seconds_interval
        self.function = function


def cron_worker(*_):
    if not should_run("main", 60):
        return

    # customize this part:
    from application.models import Event
    tasks = [
        CronTask("events", 60 * 30, Event.clean_stale_objects),
        # ...
    ]

    for task in tasks:
        if should_run(task.name, task.seconds_interval):
            task.function()


def cron_middleware(get_response):

    def middleware(request):
        response = get_response(request)
        threading.Thread(target=cron_worker).start()
        return response

    return middleware

models/cron.py

from django.db import models


class CronJob(models.Model):
    name = models.CharField(max_length=10, primary_key=True)
    last_ran = models.DateTimeField()

settings.py

MIDDLEWARE = [
    ...
    'application.middleware.cron_middleware',
    ...
]

0

簡単な方法は、Django Documentationを参照してカスタムシェルコマンドを記述し、Linuxでcronjobを使用して実行することです。ただし、RabbitMQのようなメッセージブローカーとセロリを組み合わせて使用​​することを強くお勧めします。多分あなたはこのチュートリアルを見ることができます

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.