• APScheduler 学习笔记


    APScheduler 学习笔记

    1. 简介

    pass

    2. 安装

    2.1 使用pip安装

    pip install apscheduler
    

    2.2 下载后执行python
    下载地址:APScheduler · PyPI

    python setup.py install
    

    3 基本概念

    APScheduler 有四种组件分别为

    1. triggers
    2. job stores
    3. executors
    4. schedulers
    eg:
    from apscheduler.schedulers.blocking import BlockingScheduler
    import time
    
    # 实例化一个调度器
    scheduler = BlockingScheduler()
    
    def job1():
        print "%s: 执行任务"  % time.asctime()
    
    # 添加任务并设置触发方式为3s一次
    scheduler.add_job(job1, 'interval', seconds=3)
    
    # 开始运行调度器
    scheduler.start()
    

    4 schedulers任务调度组件

    调度器 说明
    BlockingScheduler 调度器是应用中唯一要运行的东西时。
    BackgroundScheduler 当没有运行任何其他框架,并希望调度器在应用的后台执行时使用。
    AsyncIOScheduler 程序使用了asyncio(一个异步框架)时使用。
    GeventScheduler 程序使用了gevent(高性能的Python并发框架)时使用。
    TornadoScheduler 程序基于Tornado(一个web框架)时使用。
    TwistedScheduler 程序基于Tornado(一个web框架)的时候使用。
    QtScheduler 应用是一个Qt应用的时候可以使用

    4.1 BlockingScheduler

    from apscheduler.schedulers.blocking import BlockingScheduler
    import time
    
    scheduler = BlockingScheduler()
    
    def job_test():
        print "%s: 执行任务"  % time.asctime()
    
    scheduler.add_job(job_test, 'interval', seconds=3)
    scheduler.start()
    

    4.2 BackgroundScheduler

    from apscheduler.schedulers.background import BackgroundScheduler
    import time
    
    scheduler = BackgroundScheduler()
    
    def job_test():
        print "%s: 执行任务"  % time.asctime()
    
    scheduler.add_job(job_test, 'interval', seconds=3)
    scheduler.start()
    

    4.3 AsynclOScheduler

    from apscheduler.schedulers.asyncio import AsyncIOScheduler
    try:
        import asyncio
    except ImportError:
        import trollius as asyncio
    ...
    ...
    # while True:pass 
    try:
        asyncio.get_event_loop().run_forever()
    except (KeyboardInterrupt, SystemExit):
        pass
    

    4.4 GeventScheduler

    from apscheduler.schedulers.gevent import GeventScheduler
    
    ...
    ...
    
    g = scheduler.start()
    # while True:pass
    try:
        g.join()
    except (KeyboardInterrupt, SystemExit):
        pass
    

    4.5 TornadoScheduler

    from tornado.ioloop import IOLoop
    from apscheduler.schedulers.tornado import TornadoScheduler
    
    ...
    ...
    
    # while True:pass
    try:
        IOLoop.instance().start()
    except (KeyboardInterrupt, SystemExit):
        pass
    

    4.6 TwistedScheduler:Twisted

    from twisted.internet import reactor
    from apscheduler.schedulers.twisted import TwistedScheduler
    
    ...
    ...
    
    # while True:pass
    try:
        reactor.run()
    except (KeyboardInterrupt, SystemExit):
        pass
    

    4.7 调度器操作

    开启 scheduler.start()
    关闭 scheduler.shutdown()
    暂停 scheduler.pause()
    继续 scheduler.resume()

    5. triggers任务触发器组件

    当调度作业的时,需要为这个作业选择一个触发器,用来描述这个作业何时被触,任务触发器组件,提供有三种内置的任务触发方式:

    触发方式类型 说明
    date 在某个时间点只运行一次作业时使用
    interval 按固定的时间间隔运行作业时使用
    cron 类linux下的crontab格式,属于定时调度

    5.1 一次性调度data

    参数 格式 说明
    run_date datetime/str 在某个时间点只运行一次作业时使用
    timezone datetime.tzinfo/str 指定时区
    eg:
    # 2016-12-12运行一次job_function
    sched.add_job(job_function, 'date', run_date=date(2016, 12, 12), args=['text'])
    
    # 2016-12-12 12:00:00运行一次job_function
    sched.add_job(job_function, 'date', run_date=datetime(2016, 12, 12, 12, 0, 0), args=['text'])
    

    5.2 间隔调度interval

    参数 格式 说明
    year int/str
    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 指定时区

    eg:

    
    

    5.3 定时调度cron

    参数 格式 说明
    year int/str
    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 指定时区
    eg:
    # job_function将会在6,7,8,11,12月的第3个周五的1,2,3点运行
    sched.add_job(job_function, 'cron', month='6-8,11-12', day='3rd fri', hour='0-3')
    
    # 截止到2016-12-30 00:00:00,每周一到周五早上五点半运行job_function
    sched.add_job(job_function, 'cron', day_of_week='mon-fri', hour=5, minute=30, end_date='2016-12-31')
    

    6.job_stores 任务保存组件

    提供任务保存方式

    6.1. base

    6.2. memory

    6.3. mongodb

    scheduler.add_jobstore('mongodb', collection='example_jobs')
    

    6.4. redis

    scheduler.add_jobstore('redis', jobs_key='example.jobs', run_times_key='example.run_times')
    

    6.6. rethinkdb

    scheduler.add_jobstore('rethinkdb', database='apscheduler_example')
    

    6.7. sqlalchemy

    scheduler.add_jobstore('sqlalchemy', url=url)
    

    6.7. zookeeper

    scheduler.add_jobstore('zookeeper', path='/example_jobs')
    
    Django中使用示例:
    scheduler.add_jobstore(DjangoJobStore(), "default")
    

    7. executors 任务调度组件

    7.1 base

    pass

    7.2 debug

    pass

    7.3 gevent

    pass

    7.4 pool(max_workers=10)

    pass

    7.5 twisted

    pass

    8. 任务操作

    8.1 add_job添加任务

    如果使用了任务的存储,开启时最好添加replace_existing=True,否则每次开启都会创建任务的副本
    开启后任务不会马上启动,可修改trigger参数

    8.2 remove_job删除任务

    # 根据任务实例删除
    job = scheduler.add_job(myfunc, 'interval', minutes=2)
    job.remove()
    
    # 根据任务id删除
    scheduler.add_job(myfunc, 'interval', minutes=2, id='my_job_id')
    scheduler.remove_job('my_job_id')
    

    8.3 pause_job暂停任务

    8.4 resume_job继续任务

    job = scheduler.add_job(myfunc, 'interval', minutes=2)
    # 根据任务实例
    job.pause()
    job.resume()
    
    # 根据任务id暂停
    scheduler.add_job(myfunc, 'interval', minutes=2, id='my_job_id')
    scheduler.pause_job('my_job_id')
    scheduler.resume_job('my_job_id')
    

    8.5 modify 任务修饰

    job.modify(max_instances=6, name='Alternate name')
    

    8.6 reschedule_job重设任务

    scheduler.reschedule_job('my_job_id', trigger='cron', minute='*/5')
    

    调度示例(摘录于https://zhuanlan.zhihu.com/p/95563033)

    
    import asyncio
    import datetime
    
    from apscheduler.events import EVENT_JOB_EXECUTED
    from apscheduler.executors.asyncio import AsyncIOExecutor
    from apscheduler.jobstores.redis import RedisJobStore  # 需要安装redis
    from apscheduler.schedulers.asyncio import AsyncIOScheduler
    from apscheduler.triggers.interval import IntervalTrigger
    from apscheduler.triggers.cron import CronTrigger
    
    # 定义jobstore  使用redis 存储job信息
    default_redis_jobstore = RedisJobStore(
        db=2,
        jobs_key="apschedulers.default_jobs",
        run_times_key="apschedulers.default_run_times",
        host="127.0.0.1",
        port=6379,
        password="test"
    )
    
    # 定义executor 使用asyncio是的调度执行规则
    first_executor = AsyncIOExecutor()
    
    # 初始化scheduler时,可以直接指定jobstore和executor
    init_scheduler_options = {
        "jobstores": {
            # first 为 jobstore的名字,在创建Job时直接直接此名字即可
            "default": default_redis_jobstore
        },
        "executors": {
            # first 为 executor 的名字,在创建Job时直接直接此名字,执行时则会使用此executor执行
            "first": first_executor
        },
        # 创建job时的默认参数
        "job_defaults": {
            'coalesce': False,  # 是否合并执行
            'max_instances': 1  # 最大实例数
        }
    }
    # 创建scheduler
    scheduler = AsyncIOScheduler(**init_scheduler_options)
    
    # 启动调度
    scheduler.start()
    
    second_redis_jobstore = RedisJobStore(
        db=2,
        jobs_key="apschedulers.second_jobs",
        run_times_key="apschedulers.second_run_times",
        host="127.0.0.1",
        port=6379,
        password="test"
    )
    
    scheduler.add_jobstore(second_redis_jobstore, 'second')
    # 定义executor 使用asyncio是的调度执行规则
    second_executor = AsyncIOExecutor()
    scheduler.add_executor(second_executor, "second")
    
    
    # ***********               关于 APScheduler中有关Event相关使用示例               *************
    # 定义函数监听事件
    def job_execute(event):
        """
        监听事件处理
        :param event:
        :return:
        """
        print(
            "job执行job:
    code => {}
    job.id => {}
    jobstore=>{}".format(
                event.code,
                event.job_id,
                event.jobstore
            ))
    
    
    # 给EVENT_JOB_EXECUTED[执行完成job事件]添加回调,这里就是每次Job执行完成了我们就输出一些信息
    scheduler.add_listener(job_execute, EVENT_JOB_EXECUTED)
    
    
    # ***********               关于 APScheduler中有关Job使用示例               *************
    # 使用的是asyncio,所以job执行的函数可以是一个协程,也可以是一个普通函数,AsyncIOExecutor会根据配置的函数来进行调度,
    # 如果是协程则会直接丢入到loop中,如果是普通函数则会启用线程处理
    # 我们定义两个函数来看看执行的结果
    
    def interval_func(message):
        print("现在时间: {}".format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
        print("我是普通函数")
        print(message)
    
    
    async def async_func(message):
        print("现在时间: {}".format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
        print("我是协程")
        print(message)
    
    
    # 将上述的两个函数按照不同的方式创造触发器来执行
    # ***********               关于 APScheduler中有关Trigger使用示例               *************
    # 使用Trigger有两种方式,一种是用类创建使用,另一个是使用字符串的方式
    # 使用字符串指定别名, scheduler初始化时已将其定义的trigger加载,所以指定字符串可以直接使用
    
    
    if scheduler.get_job("interval_func_test", "default"):
        # 存在的话,先删除
        scheduler.remove_job("interval_func_test", "default")
    
    # 立马开始 2分钟后结束, 每10s执行一次 存储到first jobstore  second执行
    scheduler.add_job(interval_func, "interval",
                      args=["我是10s执行一次,存放在jobstore default, executor default"],
                      seconds=10,
                      id="interval_func_test",
                      jobstore="default",
                      executor="default",
                      start_date=datetime.datetime.now(),
                      end_date=datetime.datetime.now() + datetime.timedelta(seconds=240))
    
    # 先创建tigger
    trigger = IntervalTrigger(seconds=5)
    
    if scheduler.get_job("interval_func_test_2", "second"):
        # 存在的话,先删除
        scheduler.remove_job("interval_func_test_2", "second")
    # 每隔5s执行一次
    scheduler.add_job(async_func, trigger, args=["我是每隔5s执行一次,存放在jobstore second, executor = second"],
                      id="interval_func_test_2",
                      jobstore="second",
                      executor="second")
    
    # 使用协程的函数执行,且使用cron的方式配置触发器
    
    if scheduler.get_job("cron_func_test", "default"):
        # 存在的话,先删除
        scheduler.remove_job("cron_func_test", "default")
    
    # 立马开始 每10s执行一次
    scheduler.add_job(async_func, "cron",
                      args=["我是 每分钟 30s  时执行一次,存放在jobstore default, executor default"],
                      second='30',
                      id="cron_func_test",
                      jobstore="default",
                      executor="default")
    
    # 先创建tigger
    trigger = CronTrigger(second='20,40')
    
    if scheduler.get_job("cron_func_test_2", "second"):
        # 存在的话,先删除
        scheduler.remove_job("cron_func_test_2", "second")
    # 每隔5s执行一次
    scheduler.add_job(async_func, trigger, args=["我是每分钟 20s  40s时各执行一次,存放在jobstore second, executor = second"],
                      id="cron_func_test_2",
                      jobstore="second",
                      executor="second")
    
    # 使用创建trigger对象直接创建
    print("启动: {}".format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
    asyncio.get_event_loop().run_forever()
    

    输出结果部分截取

    启动之后,每隔5s运行一次的JOB

    启动: 2019-12-05 14:13:11
    【这部分是定义的协程函数输出的内容】
    现在时间: 2019-12-05 14:13:16
    我是协程
    我是每隔5s执行一次,存放在jobstore second, executor = second
    【这部分是监听job执行完成之后的回调输出】
    job执行job: code => 4096
    job.id => interval_func_test_2
    jobstore=>second
    

    在20s和40s时各执行一次的Job

    现在时间: 2019-12-05 14:13:20
    我是协程
    我是每分钟 20s 40s时各执行一次,存放在jobstore second, executor = second
    job执行
    job: code => 4096
    job.id => cron_func_test_2
    jobstore=>second
    

    每隔10s执行一次的job

    现在时间: 2019-12-05 14:13:21
    我是普通函数
    我是10s执行一次,存放在jobstore default, executor default
    现在时间: 2019-12-05 14:13:21
    我是协程
    我是每隔5s执行一次,存放在jobstore second, executor = second
    job执行job: code => 4096
    job.id => interval_func_test
    jobstore=>default
    job执行
    job: code => 4096
    job.id => interval_func_test_2
    jobstore=>second
    
    

    每隔5s执行一次的Job

    现在时间: 2019-12-05 14:13:26
    我是协程
    我是每隔5s执行一次,存放在jobstore second, executor = second
    job执行
    job: code => 4096
    job.id => interval_func_test_2
    jobstore=>second
    

    每分钟30s时执行一次

    现在时间: 2019-12-05 14:13:30
    我是协程
    我是 每分钟 30s 时执行一次,存放在jobstore default, executor default
    job执行
    job: code => 4096
    job.id => cron_func_test
    jobstore=>default
    
  • 相关阅读:
    (Java实现) 删数问题
    (Java实现) 车站
    (Java实现) 活动选择
    (Java实现) 过河卒
    (Java实现) 美元汇率
    (Java实现) 零件分组
    (Java实现) 图的m着色问题
    (Java实现) 数塔问题
    Java实现 蓝桥杯VIP 算法训练 数的划分
    DirectUI的消息流转
  • 原文地址:https://www.cnblogs.com/yanhui1995/p/14951176.html
Copyright © 2020-2023  润新知