django 定时任务第三方库apscheduler

1、apscheduler未安装的需要自己安装,安装命令如下:

pip install apscheduler

  

2、apscheduler库有很多不同类型的调度器,其他我也不懂,只知道BlockingScheduler与BackgroundScheduler,这是比较常用的两种
  区别主要在于BlockingScheduler会阻塞主线程的运行,而BackgroundScheduler不会阻塞。所以,我们在不同的情况下,选择不同的调度器:
  BlockingScheduler: 调用start函数后会阻塞当前线程。当调度器是你应用中唯一要运行的东西时使用(下面写的就是这种调度)
  BackgroundScheduler: 调用start后主线程不会阻塞。当你不运行任何其他框架时使用,并希望调度器在你应用的后台执行
  用人话说就是:用BlockingScheduler创建的类,调用start()函数开始运行后,会阻塞(相当于停止)当前已在运行的线程,只执行当前的定时任务,运行到你主动关掉为止
  而BackgroundScheduler创建的类,调用start后主线程不会阻塞,会继续运行下一行代码,如果后面没有死循环什么的,订的时间又比较长,会出现定时还没生效,代码已经运行结束的情况
  参考文章:https://www.cnblogs.com/will-wu/p/14721592.html

 

3、apscheduler的触发器
  apscheduler的触发器有三种:date(日期触发),interval(固定间隔触发),cron(周期触发)

    date表示具体的一次性任务,interval表示循环任务,cron表示定时任务  

  3.1、日期触发:date,特定的时间点触发,最基本的一种调度,作业只会执行一次
    run_date(datetime or str) 任务运行的日期或者时间
    timezone(datetime.tzinfo or str) 指定时区

# 导入BlockingScheduler调度器
from apscheduler.schedulers.blocking import BlockingScheduler
from datetime import datetime

# 封装函数待用
def print_hours_now():
    print('小时:%s' % datetime.now().strftime("%Y-%m-%d %H:%M:%S"))

# 创建一个对象
timing_type = BlockingScheduler()

# run_date时间到了之后,开始执行print_hours_now
timing_type.add_job(print_hours_now,'date',run_date='2021-04-30 16:13:00')
# 或这样写
# timing_type.add_job(func=print_hours_now,trigger='date',run_date='2021-04-30 16:13:00')

# 立即执行
timing_type.add_job(print_hours_now,'date')

# 等待触发时间到达,开始执行指定任务
timing_type.start()

  

3.2、interval:固定间隔触发
    year:每隔X年执行一次
    weeks:每隔X周执行一次 weeks=X,范围1-12
    days:每隔X天执行一次,范围1-31
    hours: 每隔几小时执行一次 | hours=0,范围0-23
    minutes: 每隔几分执行一次 | minutes=0,范围0-59
    seconds: 每隔几秒执行一次 | seconds=0,范围0-59
    start_date: 最早执行时间 | start_date=None,范围是年月日的组合字符串
    end_date: 最晚执行时间 | end_date=None,范围是年月日的组合字符串
    timezone: 执行时间区间 | timezone=None,范围是年月日的组合字符串

from apscheduler.schedulers.blocking import BlockingScheduler
from datetime import datetime

def print_minutes_now():
    print('打印时间:%s' % datetime.now().strftime("%Y-%m-%d %H:%M:%S"))

timing_type = BlockingScheduler()
# 在start_date到end_date时间段内,每隔5s执行一次print_minutes_now;其中,func=这些可以省略,start_date和end_date可以单独使用,
# timing_type.add_job(func=print_minutes_now,trigger='interval',seconds=5,start_date='2021-05-04 11:40',end_date='2021-05-04 11:41:00')
# 在end_date之前,每隔0.2小时运行一次print_minutes_now
timing_type.add_job(func=print_minutes_now,trigger='interval',minutes=2,end_date='2021-05-08 11:41:00')
# 每隔1小时执行一次
timing_type.add_job(func=print_minutes_now,trigger='interval',hours=1)
# 启动调度器
timing_type.start()

  

3.3、cron:周期触发,在特定时间周期性地触发
    cron参数:
      year(int or str) 年,4位数字
      month(int or str) 月(范围1-12)
      day(int or str) 日(范围1-31)
      week(int or str) 周(范围1-53)
      day_of_week(int or str) 周内第几天或者星期几(范围0-6或者mon,tue,wed,thu,fri,stat,sun)
      hour(int or str) 时(0-23)
      minute(int or str) 分(0-59)
      second(int or str) 秒(0-59)
      start_date(datetime or str) 最早开始日期(含)
      end_date(datetime or str) 最晚结束日期(含)
      timezone(datetime.tzinfo or str) 指定时区

    表达式:
      * 所有 通配符。例:minutes=*即每分钟触发
      */a 所有 可被a整除的通配符。
      a-b 所有 范围a-b触发
      a-b/c 所有 范围a-b,且可被c整除时触发
      xth y 日 第几个星期几触发。x为第几个,y为星期几
      last x 日 一个月中,最后个星期几触发
      last 日 一个月最后一天触发
      x,y,z 所有 组合表达式,可以组合确定值或上方的表达式

from apscheduler.schedulers.blocking import BlockingScheduler
from datetime import datetime

def print_time_now():
    print('打印当前时间:',datetime.now().strftime("%Y-%m-%d %H:%M:%S"))

timing_type = BlockingScheduler()
# 每个月每天的17:36,打印当前时间,*代表0-59
# timing_type.add_job(print_time_now,'cron',month='*',day='*',hour=17,minute=36,second='*')
# 每天的每小时16分的零秒开始到59秒执行print_time_now(年月日时不写的时候会默认为所有,秒不写则默认为0)
timing_type.add_job(func=print_time_now, trigger='cron',minute='16',second='0-59')
# 周一到周五6:30执行timing_type.add_job(print_time_now, "cron",day_of_week = "1-5", hour = 6, minute = 30)
# 启动调度器 timing_type.start()

  

示例:

#封装邮件发送方法
from django.core.mail import send_mail


def send_email(email_user):
    send_mail(
        subject='这里是邮件标题',
        message='这里是邮件内容',
        from_email='test@qq.com',  # 发件人
        recipient_list=[email_user],  # 收件人
        #收件人可以直接写,也可以从setting.py中配置中导入
        fail_silently=False
    )
    print("邮件发送成功")
    return "邮件已发送"


#定时任务
from apscheduler.schedulers.background import BackgroundScheduler

#待定时执行的函数
def update_days():
    all_borrow_book = Borrow.objects.filter(borrow_status=2)
    now = datetime.date.today()
    # all_bookname = all_borrow_book.book_id
    for book in all_borrow_book:
        id = book.id
        user_id = book.user_id
        book_id = book.book_id
        print("userid:",user_id)
        email_user = User.objects.get(username=user_id).email
        lib_book = Book.objects.get(book_number=book_id)
        update_book = Borrow.objects.get(id=id)
        return_date = book.return_date
        update_days = return_date.__sub__(now).days
        update_book.surplus_days = update_days
        if update_days < 0:
            update_book.borrow_status = -1
            update_book.save()
            lib_book.book_status = -1
            lib_book.save()
            send_email(email_user)
        else:
            update_book.save()
        print("surplus_days: ",update_days)


#开启定时工作
try:
    # 实例化调度器
    scheduler = BackgroundScheduler()
    # scheduler.add_job(my_job, 'interval', minutes=10)
    scheduler.add_job(update_days,'cron',month='*',day='*',hour=19,minute=38,second=00)
    scheduler.start()
except Exception as e:
    print(e)

  

https://apscheduler.readthedocs.io/en/3.x/userguide.html#code-examples

https://www.cnblogs.com/will-wu/p/14731728.html

 

posted @ 2022-03-31 19:54  香菜哥哥  阅读(746)  评论(0编辑  收藏  举报