zoukankan      html  css  js  c++  java
  • APScheduler 定时任务使用总结

    介绍:

    APScheduler的全称是Advanced Python Scheduler。它是一个轻量级的 Python 定时任务调度框架。APScheduler 支持三种调度任务:固定时间间隔,固定时间点(日期),Linux 下的 Crontab 命令。同时,它还支持异步执行、后台执行调度任务。

    基本概念
    1. APScheduler四大组件:
    触发器 triggers       用于设定触发任务的条件
    
    任务储存器 job stores  用于存放任务,把任务存放在内存或数据库中
    
    执行器 executors      用于执行任务,可以设定执行模式为单线程或线程池
    
    调度器 schedulers     把上方三个组件作为参数,通过创建调度器实例来运行
    1.1 触发器 triggers 
    触发器包含调度逻辑。每个任务都有自己的触发器,用于确定何时应该运行作业。除了初始配置之外,触发器完全是无状态的
    1.2 任务储存器 job stores
    默认情况下,任务存放在内存中。也可以配置存放在不同类型的数据库中。如果任务存放在数据库中,那么任务的存取有一个序列化和反序列化的过程,同时修改和搜索任务的功能也是由任务储存器实现。
    
    注意一个任务储存器不要共享给多个调度器,否则会导致状态混乱
    1.3 执行器 executors
    任务会被执行器放入线程池或进程池去执行,执行完毕后,执行器会通知调度器。
    1.4 调度器 schedulers
    一个调度器由上方三个组件构成,一般来说,一个程序只要有一个调度器就可以了。开发者也不必直接操作任务储存器、执行器以及触发器,因为调度器提供了统一的接口,通过调度器就可以操作组件,比如任务的增删改查。

    调度器工作流程:
    2. 调度器组件详解
    根据开发需求选择相应的组件,下面是不同的调度器组件:
    BlockingScheduler      
    阻塞式调度器:适用于只跑调度器的程序。
    BackgroundScheduler    
    后台调度器:适用于非阻塞的情况,调度器会在后台独立运行。
    AsyncIOScheduler       
    AsyncIO调度器,适用于应用使用AsnycIO的情况。
    GeventScheduler        
    Gevent调度器,适用于应用通过Gevent的情况。
    TornadoScheduler       
    Tornado调度器,适用于构建Tornado应用。
    TwistedScheduler       
    Twisted调度器,适用于构建Twisted应用。
    QtScheduler            
    Qt调度器,适用于构建Qt应用。
     
    3. APScheduler有三种内置的触发器:
    date
    日期:触发任务运行的具体日期
    interval 
    间隔:触发任务运行的时间间隔
    cron 
    周期:触发任务运行的周期

    3.1  date 是最基本的一种调度,作业任务只会执行一次。它表示特定的时间点触发。它的参数如下:
    参数 说明
    run_date (datetime 或 str) 作业的运行日期或时间
    timezone (datetime.tzinfo 或 str) 指定时区

    from datetime import datetime
    from datetime import date
    from apscheduler.schedulers.blocking import BlockingScheduler
    
    def job(text):    
        print(text)
    
    scheduler = BlockingScheduler()
    # 在 2019-8-30 运行一次 job 方法
    scheduler.add_job(job, 'date', run_date=date(2019, 8, 30), args=['text1'])
    # 在 2019-8-30 01:00:00 运行一次 job 方法
    scheduler.add_job(job, 'date', run_date=datetime(2019, 8, 30, 1, 0, 0), args=['text2'])
    # 在 2019-8-30 01:00:01 运行一次 job 方法
    scheduler.add_job(job, 'date', run_date='2019-8-30 01:00:00', args=['text3'])
    
    scheduler.start()
    3.2 interval 周期触发任务
    参数 说明
    weeks (int) 间隔几周
    days (int) 间隔几天
    hours (int) 间隔几小时
    minutes (int) 间隔几分钟
    seconds (int) 间隔多少秒
    start_date (datetime 或 str) 开始日期
    end_date (datetime 或 str) 结束日期
    timezone (datetime.tzinfo 或str) 时区
    import time
    from apscheduler.schedulers.blocking import BlockingScheduler
    
    def job(text):    
        t = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
        print('{} --- {}'.format(text, t))
    
    scheduler = BlockingScheduler()
    # 每隔 1分钟 运行一次 job 方法
    scheduler.add_job(job, 'interval', minutes=1, args=['job1'])
    # 在 2019-08-29 22:15:00至2019-08-29 22:17:00期间,每隔1分30秒 运行一次 job 方法
    scheduler.add_job(job, 'interval', minutes=1, seconds = 30, start_date='2019-08-29 22:15:00', end_date='2019-08-29 22:17:00', args=['job2'])
    
    scheduler.start()
    
    '''
    运行结果:
    job2 --- 2019-08-29 22:15:00
    job1 --- 2019-08-29 22:15:46
    job2 --- 2019-08-29 22:16:30
    job1 --- 2019-08-29 22:16:46
    job1 --- 2019-08-29 22:17:46
    ...余下省略...
    '''
     3.3 cron 触发器     在特定时间周期性地触发,和Linux crontab格式兼容。它是功能最强大的触发器。
    参数 说明
    year (int 或 str) 年,4位数字
    month (int 或 str) 月 (范围1-12)
    day (int 或 str) 日 (范围1-31)
    week (int 或 str) 周 (范围1-53)
    day_of_week (int 或 str) 周内第几天或者星期几 (范围0-6 或者 mon,tue,wed,thu,fri,sat,sun)
    hour (int 或 str) 时 (范围0-23)
    minute (int 或 str) 分 (范围0-59)
    second (int 或 str) 秒 (范围0-59)
    start_date (datetime 或 str) 最早开始日期(包含)
    end_date (datetime 或 str) 最晚结束时间(包含)
    timezone (datetime.tzinfo 或str) 指定时区
    表达式 参数类型 描述
    * 所有 通配符。例:minutes=*即每分钟触发
    */a 所有 可被a整除的通配符
    a-b 所有 范围a-b触发
    a-b/c 所有 范围a-b,且可被c整除时触发
    xth y 第几个星期几触发。x为第几个,y为星期几
    last x 一个月中,最后个星期几触发
    last 一个月最后一天触发
    x,y,z 所有 组合表达式,可以组合确定值或上方的表达式
        import time
        from apscheduler.schedulers.blocking import BlockingScheduler
    
    
        def job(text):
            t = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
            print('{} --- {}'.format(text, t))
    
    
        scheduler = BlockingScheduler()
        # 在每天22点,每隔 1分钟 运行一次 job 方法
        scheduler.add_job(job, 'cron', hour=22, minute='*/1', args=['job1'])
        # 在每天22和23点的25分,运行一次 job 方法
        scheduler.add_job(job, 'cron', hour='22-23', minute='25', args=['job2'])
        # 在每天 8 点,运行一次 job 方法
        scheduler.add_job(job, 'cron', hour='8', args=['job2'])
        # 在每天 8 点 20点,各运行一次 job 方法    设置最大运行实例数
        scheduler.add_job(job, 'cron', hour='8, 20', minute=30, max_instances=4)
        
        scheduler.start()
    
        '''
        运行结果:
        job1 --- 2019-08-29 22:25:00
        job2 --- 2019-08-29 22:25:00
        job1 --- 2019-08-29 22:26:00
        job1 --- 2019-08-29 22:27:00
        ...余下省略...
        '''
    3.4  通过装饰器scheduled_job()添加方法

    添加任务的方法有两种:

    (1)通过调用add_job()---见上面1至3代码
    (2)通过装饰器scheduled_job():
    第一种方法是最常用的方法。第二种方法主要是方便地声明在应用程序运行时不会更改的任务。该 add_job()方法返回一个apscheduler.job.Job实例,可以使用该实例稍后修改或删除该任务。

    import time
    from apscheduler.schedulers.blocking import BlockingScheduler
    
    scheduler = BlockingScheduler()
    
    @scheduler.scheduled_job('interval', seconds=5)
    def job1():    
        t = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
        print('job1 --- {}'.format(t))
    
    @scheduler.scheduled_job('cron', second='*/7')
    def job2():    
        t = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
        print('job2 --- {}'.format(t))
    
    scheduler.start()
    
    '''
    运行结果:
    job2 --- 2019-08-29 22:36:35
    job1 --- 2019-08-29 22:36:37
    job2 --- 2019-08-29 22:36:42
    job1 --- 2019-08-29 22:36:42
    job1 --- 2019-08-29 22:36:47
    job2 --- 2019-08-29 22:36:49
    ...余下省略...
    '''
    注意:夏令时问题

    有些timezone时区可能会有夏令时的问题。这个可能导致令时切换时,任务不执行或任务执行两次。避免这个问题,可以使用UTC时间,或提前预知并规划好执行的问题。

    # 在Europe/Helsinki时区, 在三月最后一个周一就不会触发;在十月最后一个周一会触发两次
    sched.add_job(job_function, 'cron', hour=3, minute=30)

    详细参考 : http://www.chenxm.cc/article/829.html

  • 相关阅读:
    判断是否可以点击
    窗口截图
    设置等待操作
    时间控件处理
    eclipse小技巧
    Angular 学习1
    MVC 中引用Angularjs
    Bootstrap 侧边栏 导航栏
    C# 直接使用sql语句对数据库操作 (cmd.ExecuteNonQuery)
    sql 常用的语句(sql 创建表结构 修改列 清空表)
  • 原文地址:https://www.cnblogs.com/luochunxi/p/14115929.html
Copyright © 2011-2022 走看看