apscheduler模块

https://zhuanlan.zhihu.com/p/95563033

1 概念

名词

job 最小执行单位,创建一个Job,然后指定要执行的函数

trigger 触发器,根据时间规则,计算得到下次执行时间。

executer

next_run_time  触发规则有trigger的时间,或者这个定时执行

func job的执行函数

args job执行函数的参数

kwargs 执行函数的关键字参数

 

trigger

Trigger有多种种类,指定时间的DateTrigger,指定间隔时间的IntervalTrigger,像Linux的crontab一样的CronTrigger

 

Executor 

Executor在scheduler中初始化,另外也可通过scheduler的add_executor动态添加Executor。
每个executor都会绑定一个alias,这个作为唯一标识绑定到Job,在实际执行时会根据Job绑定的executor
找到实际的执行器对象,然后根据执行器对象执行Job

Executor的种类会根据不同的调度来选择,如果选择AsyncIO作为调度的库,那么选择AsyncIOExecutor,如果
选择tornado作为调度的库,选择TornadoExecutor,如果选择启动进程作为调度,
选择ThreadPoolExecutor或者ProcessPoolExecutor都可以

Executor的选择需要根据实际的scheduler来选择不同的执行器

 

Jobstore 

Jobstore在scheduler中初始化,另外也可通过scheduler的add_jobstore动态添加Jobstore。每个jobstore
都会绑定一个alias,scheduler在Add Job时,根据指定的jobstore在scheduler中找到相应的jobstore,并
将job添加到jobstore中。

Jobstore主要是通过pickle库的loads和dumps【实现核心是通过python的__getstate__和__setstate__重写
实现】,每次变更时将Job动态保存到存储中,使用时再动态的加载出来,作为存储的可以是redis,也可以
是数据库【通过sqlarchemy这个库集成多种数据库】,也可以是mongodb等

 

Event 

Event是APScheduler在进行某些操作时触发相应的事件,用户可以自定义一些函数来监听这些事件,
当触发某些Event时,做一些具体的操作

常见的比如。Job执行异常事件 EVENT_JOB_ERROR。Job执行时间错过事件 EVENT_JOB_MISSED。

 

Listener 

Listener表示用户自定义监听的一些Event,当Job触发了EVENT_JOB_MISSED事件时
可以根据需求做一些其他处理。

 

Scheduler 

Scheduler是APScheduler的核心,所有相关组件通过其定义。scheduler启动之后,将开始按照配置的任务进行调度。
除了依据所有定义Job的trigger生成的将要调度时间唤醒调度之外。当发生Job信息变更时也会触发调度。

scheduler可根据自身的需求选择不同的组件,如果是使用AsyncIO则选择AsyncIOScheduler,使用tornado则
选择TornadoScheduler。

 

tornado案例

from datetime import datetime
from tornado.ioloop import IOLoop, PeriodicCallback
from tornado.web import RequestHandler, Application
from apscheduler.schedulers.tornado import TornadoScheduler
import json

scheduler = TornadoScheduler()


def init_scheduler():
    global scheduler
    url = "mysql+pymysql://root:123@192.168.1.2/codo_cron?charset=utf8"
    scheduler.add_jobstore(jobstore="sqlalchemy", url=url, tablename='api_job')     # 持久化存储配置,表会自动创建
    scheduler.start()
    print('[Scheduler Init]APScheduler has been started')


# 要执行的定时任务在这里
def task1():
    print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
def task2():
    print(datetime.now().strftime('%Y/%m/%d %H:%M:%S'))


class SchedulerHandler(RequestHandler):
    def post(self):
        data = json.loads(self.request.body.decode("utf-8"))

        # 判断定时器格式
        cron = data.get('cron').strip().split(' ')
        if len(cron) != 6:
            return self.write(dict(code=-1, msg='添加失败,格式错误'))

        cmd = data.get('cmd', None)
        job_id = data.get('job_id', None)

        if job_id:
            try:
                cron_rel = dict(second=cron[0], minute=cron[1], hour=cron[2], day=cron[3], month=cron[4],
                                day_of_week=cron[5])
                scheduler.add_job(func=__name__ + ':' + cmd,  # 可调用的函数,(e.g.  package.module:some.object)
                                  trigger='cron',   # 触发器类型,(e.g. ``date``, ``interval`` or ``cron``)
                                  # kwargs={'cmd': cmd, 'job_id': job_id},   # 调用函数的关键字参数的字典,函数没有参数就不需要
                                  id=job_id,     # job 唯一标识
                                  **cron_rel    # 定时任务格式,
                                                # (e.g. second=10, minute=*, hour=*, day=*, month=*, day_of_week=*)
                                                # 代表每分钟的第10秒执行一次
                                  )

                return self.write(dict(code=0, msg='添加成功', job_id=job_id))
            except Exception as e:
                return self.write(dict(code=-1, msg='添加失败: %s' % e))


if __name__ == "__main__":
    routes = [
        (r"/scheduler/?", SchedulerHandler),
    ]
    init_scheduler()
    app = Application(routes, debug=True)
    app.listen(8888)
    IOLoop.current().start()

  

posted @ 2020-09-18 16:01  jabbok  阅读(314)  评论(0编辑  收藏  举报