django-apscheduler scheduled task

Install the apscheduler module

pip install apscheduler 
pip install django-apscheduler 

Add django-apscheduler to INSTALLED_APPS in the settings of the project

 INSTALLED_APPS = [

   ....

'django_apscheduler',

]

carried out:

# python manage.py migrate 
no other table structure do not have to run python manage.py makemigrations

Two tables will be created: django_apscheduler_djangojob / django_apscheduler_djangojobexecution
can easily manage scheduled tasks by entering the background management.

In the urls.py file in the Django project directory, or the main urls.py, introduce the following content

from apscheduler.schedulers.background import BackgroundScheduler
from django_apscheduler.jobstores import DjangoJobStore, register_events, register_job

scheduler = BackgroundScheduler()
scheduler.add_jobstore(DjangoJobStore(), "default")


# 时间间隔3秒钟打印一次当前的时间
@register_job(scheduler, "interval", seconds=3, id='test_job')
def test_job():
    print("我是apscheduler任务")
# per-execution monitoring, call register_events on your scheduler
register_events(scheduler)
scheduler.start()
print("Scheduler started!")

 

 

 The results are as follows:

 

 

 

The difference between the two schedulers in APScheduler and the problems to be paid attention to during use

There are many different types of schedulers in APScheduler, BlockingScheduler and BackgroundScheduler are the two most commonly used schedulers. The main difference is that BlockingScheduler will block the main thread, while BackgroundScheduler will not block. Therefore, we choose different schedulers in different situations:

  • BlockingScheduler: Calling the start function will block the current thread. Used when the scheduler is the only thing in your application that you want to run (as in the example above).
  • BackgroundScheduler: The main thread will not block after calling start. Use when you are not running any other framework and want the scheduler to execute in the background of your application.

A real example of 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)

运行结果:
job 3s
job 3s
job 3s
job 3s

It can be seen that BlockingSchedulercalling the start function will block the current thread, resulting in the while loop in the main program will not be executed.

BackgroundSchedulerReal example

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
job 3s

It can be seen that the BackgroundSchedulercurrent thread is not blocked after calling the start function, so the logic of the while loop in the main program can be continued.

Through this output, we can also find that after calling the start function, job () does not start execution immediately. Instead, it will be scheduled for execution after waiting for 3s.

How to make the job start running after start ()

How can the job () be executed immediately after the scheduler calls the start function?

In fact, APSchedulerthere is no good way to solve this problem, but there is one of the simplest way is to run a job () before the scheduler start, as follows

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)


运行结果:
job 3s
main 1s
main 1s
main 1s
job 3s
main 1s
main 1s
main 1s

In this way, although it is not absolutely possible to "let the job start after start ()", it can also be "not waiting for the schedule, but running the job at the beginning".  

What if the job execution time is too long

If the execution time of job () takes 5s, but the scheduler is configured to call job () every 3s, what will happen? We wrote the following example:

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
Execution of job "job (trigger: interval[0:00:03], next run at: 2018-05-07 02:44:29 MST)" skipped: maximum number of running instances reached (1)
main 1s
main 1s
main 1s
job 3s
main 1s

It can be seen that after the 3s time arrives, it will not "restart a job thread", but will skip the scheduling, wait for the next cycle (waiting for another 3s), and reschedule the job ().

In order to allow multiple jobs () to run at the same time, we can also configure the parameters of the scheduler max_instances, as in the following example, we allow 2 jobs () to run at the same time

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')
        time.The result of sleep (1) 
job 3s
main 1s
main 1s
main 1s
job 3s
main 1s
main 1s
main 1s
job 3s
main 1s
main 1s
main 1s

operation:

How each job is scheduled

Through the above example, we found that the scheduler schedules the job () function regularly to achieve scheduling.

Will the job () function be scheduled to run as a process, or will it run as a thread?

In order to clarify this problem, we wrote the following program:

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
job 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

It can be seen that the process ID of each job () is the same, but the thread ID is different. Therefore, job () is ultimately scheduled for execution in the form of threads.  

  

  

  

  

 

Summary of ways to trigger tasks:

date

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()

The run_dateparameters can be date type, datetime type or text type.

datetime type (for precise time)

# Execute 
sched.add_job (my_job, 'date', run_date = datetime (2009, 11, 6, 16, 30, 5), args = ['text']) at 16:30:05 on November 6, 2009

  

  

  

  

  

  

Guess you like

Origin www.cnblogs.com/weidaijie/p/12747685.html