apschedulerモジュールをインストールする
pip install apscheduler pip install django-apscheduler
プロジェクトの設定でdjango-apschedulerをINSTALLED_APPSに追加します
INSTALLED_APPS = [ .... 'django_apscheduler'、 ]
実装:
#python manage.py migrate 他のテーブル構造ではpython manage.py makemigrationsを実行する必要はありません
2つのテーブルが作成されます:django_apscheduler_djangojob / django_apscheduler_djangojobexecution
は、バックグラウンド管理を入力することで、スケジュールされたタスクを簡単に管理できます。
Djangoプロジェクトディレクトリのurls.pyファイル、またはメインのurls.pyに、次のコンテンツを導入します
apscheduler.schedulers.background輸入BackgroundSchedulerから django_apscheduler.jobstoresからDjangoJobStore、register_events、register_jobインポート スケジューラ= BackgroundScheduler() scheduler.add_jobstore(DjangoJobStore()、 "デフォルト") #时间间隔3秒钟打印一次当前的时间 @register_job(スケジューラ、 "interval"、seconds = 3、id = 'test_job') def test_job(): print( "我是apscheduler任务") #実行ごとのモニタリング、スケジューラで register_eventsを呼び出すregister_events(scheduler) scheduler.start() print (「スケジューラが開始しました!」)
結果は次のとおりです。
APSchedulerの2つのスケジューラーの違いと使用時に注意すべき問題
APSchedulerには多くの異なるタイプのスケジューラがあり、BlockingSchedulerとBackgroundSchedulerは最も一般的に使用される2つのスケジューラです。主な違いは、BlockingSchedulerはメインスレッドをブロックしますが、BackgroundSchedulerはブロックしません。したがって、さまざまな状況でさまざまなスケジューラを選択します。
BlockingScheduler
:start関数を呼び出すと、現在のスレッドがブロックされます。(上記の例のように)スケジューラがアプリケーションで実行したい唯一のものである場合に使用されます。BackgroundScheduler
:startを呼び出した後、メインスレッドはブロックしません。他のフレームワークを実行しておらず、スケジューラをアプリケーションのバックグラウンドで実行する場合に使用します。
BlockingSchedulerの実際の例
from apscheduler.schedulers.blocking import BlockingScheduler import time def job(): print( 'job 3s') if __name __ == '__ main__': sched = BlockingScheduler(timezone = 'MST') sched.add_job(job、 'interval'、 id = '3_second_job'、seconds = 3) sched.start() while(True): print( 'main 1s') time.sleep(1) 运行结果: ジョブ3s ジョブ3s ジョブ3s ジョブ3s
BlockingScheduler
start関数を呼び出すと現在のスレッドがブロックされ、メインプログラムのwhileループが実行されないことがわかります。
BackgroundScheduler
実際の例
from apscheduler.schedulers.background import BackgroundScheduler import time def job(): print( 'job 3s') if __name __ == '__ main__': sched = BackgroundScheduler(timezone = 'MST') sched.add_job(job、 'interval'、 id = '3_second_job'、seconds = 3) sched.start() while(True): print( 'main 1s') time.sleep(1) 运行结果: main 1s main 1s main 1s job 3s main 1s main 1s main 1s 仕事3秒
BackgroundScheduler
start関数を呼び出した後、現在のスレッドがブロックされていないことがわかるので、メインプログラムのwhileループのロジックを続行できます。
この出力から、start関数を呼び出した後、job()がすぐに実行を開始しないこともわかります。代わりに、3秒待ってから実行がスケジュールされます。
ジョブを開始後に実行する方法()
スケジューラが開始関数を呼び出した直後に、ジョブ()をどのように実行できますか?
実際、APScheduler
この問題を解決する良い方法はありませんが、次のように、スケジューラーの開始前にジョブ()を実行するのが最も簡単な方法の1つです。
from apscheduler.schedulers.background import BackgroundScheduler import time def job(): print( 'job 3s') if __name __ == '__ main__': job() sched = BackgroundScheduler(timezone = 'MST') sched.add_job(job、 ' interval '、id =' 3_second_job '、seconds = 3) sched.start() while(True): print(' main 1s ') time.sleep(1) 运行结果: ジョブ3s メイン1s メイン1s メイン1s ジョブ3s メイン1秒 メイン1秒 メイン1秒
このように、「ジョブをstart()の後に開始させる」ことは絶対に可能ではありませんが、「スケジュールを待たずに、最初にジョブを実行する」こともできます。
ジョブの実行時間が長すぎる場合
ジョブ()の実行時間が5秒かかるが、スケジューラがジョブ()を3秒ごとに呼び出すように構成されている場合、どうなりますか?次の例を書きました。
from apscheduler.schedulers.background import BackgroundScheduler import time def job(): print( 'job 3s') time.sleep(5) if __name __ == '__ main__': sched = BackgroundScheduler(timezone = 'MST') sched.add_job( job、 'interval'、id = '3_second_job'、seconds = 3) sched.start() while(True): print( 'main 1s') time.sleep(1) 运行结果: main 1s main 1s main 1s job 3s main 1s main 1s main 1s ジョブ「job(trigger:interval [0:00:03]、next run at:2018-05-07 02:44:29 MST)」の実行がスキップされました:実行中のインスタンスの最大数に達した(1) メイン1 メイン1 メイン1秒 ジョブ3秒 メイン1秒
3秒の時間が経過すると、「ジョブスレッドを再起動」せずに、スケジューリングをスキップして、次のサイクルを待機し(3秒待機)、ジョブを再スケジュールします()。
複数のジョブ()を同時に実行できるようにするために、スケジューラーのパラメーターを構成することもできます。max_instances
次の例のように、2つのジョブ()を同時に実行できます。
from apscheduler.schedulers.background import BackgroundScheduler import time def job(): print( 'job 3s') time.sleep(5) if __name __ == '__ main__': job_defaults = {'max_instances':2} sched = BackgroundScheduler(timezone = 'MST'、job_defaults = job_defaults) sched.add_job(job、 'interval'、id = '3_second_job'、seconds = 3) sched.start() while(True): print( 'main 1s') 時間。スリープ(1) 操作の結果: メイン1s メイン1s メイン1s ジョブ3s メイン1s メイン1s メイン1s ジョブ3s メイン1s メイン1s メイン1s ジョブ3s
各ジョブのスケジュール方法
上記の例を通して、スケジューラーはジョブ()関数を定期的にスケジュールして、スケジュールを達成することを発見しました。
ジョブ()関数はプロセスとして実行するようにスケジュールされますか、それともスレッドとして実行されますか?
この問題を明確にするために、次のプログラムを作成しました。
from apscheduler.schedulers.background import BackgroundScheduler import time、os、threading def job(): print( 'job thread_id- {0}、process_id- {1}'。format(threading.get_ident()、os.getpid()) ) time.sleep(50) if __name __ == '__ main__': job_defaults = {'max_instances':20} sched = BackgroundScheduler(timezone = 'MST'、job_defaults = job_defaults) sched.add_job(job、 'interval'、id = '3_second_job'、seconds = 3) sched.start() while(True): print( 'main 1s') time.sleep(1) 运行结結果: main 1s main 1s main 1s ジョブthread_id-10644、process_id-8872 main 1s main 1s main 1s job thread_id-3024、process_id-8872 main 1s main 1s main 1s job thread_id-6728、process_id-8872 main 1s main 1s main 1s job thread_id-11716、process_id-8872
各ジョブ()のプロセスIDは同じですが、スレッドIDが異なることがわかります。したがって、ジョブ()は最終的にスレッドの形で実行されるようにスケジュールされます。
タスクをトリガーする方法の概要:
日付
from datetime import date from apscheduler.schedulers.blocking import BlockingScheduler sched = BlockingScheduler() def my_job(text): print(text) #在2030年04月21日执行 sched.add_job(my_job、 'date'、run_date = date( 2020、04、21 )、args = ['text'])sched.start()
前記run_date
パラメータの型は、日付、日付時刻型やテキスト型であってもよいです。
日時タイプ(正確な時間)
# 2009年11月6日16:30:05にsched.add_job(my_job、 'date'、run_date = datetime(2009、11、6、16、30、5)、args = ['text'])を実行します