python-flask 技能点使用-04 定时任务框架flask_apscheduler

  1.  flask_apscheduler使用方式
    1. 使用方式一: 通过Config类配置时间规则
             # 步骤一: Config定义数据
                  JOBS = [
                      {
                          'id': '0001',
                          # 'func': '__main__:job',  # 如果是同文件的函数,则可以使用__main__:funcname的形式
                          'func': 'app.job.cron_job:job', # 如果需要应用其他文件的函数可以使用这种方法
                          'args': (1, 2),  # 这个是函数对应的入参,如果函数没有参数则无需增加args参数
                          'trigger': 'interval',
                          'seconds': 2
                      },
                      {
                          'id': '0002',
                          'func': 'app.job.cron_job:job_cron',
                          'trigger': 'cron',
                          # 'day': 21,
                          # "hour": 11,
                          # "minute": 44,
                          "second": 10
                      }
                  ]
                  SCHEDULER_API_ENABLE = True
                  SCHEDULER_TIMEZONE = "Asia/Shanghai"
              # 步骤二: python文件app/job/cron_job.py 定义方法
                  def job(a, b):
                      """定时任务执行函数"""
                      print(a + b, time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))
                  def job_cron():
                      print("====================")
              # 步骤三:运行主类中启动框架
                  if __name__ == '__main__':
                      app = Flask(__name__)                 # 实例化flask
                      app.config.from_object(Config())      # 为实例化的 flask 引入配置
                      scheduler = APScheduler()                  # 实例化 APScheduler
                      scheduler.init_app(app)                    # 把任务列表放入 flask
                      scheduler.start()                          # 启动任务列表
                      app.debug = True
                      app.run(host='0.0.0.0',port=8000)          # 启动 flask
    2. 使用方式二: 使用装饰器
              # 步骤一: 实例化APScheduler(一般放在app/__init__.py中)
                  scheduler = APScheduler()
              # 步骤二: 修饰定时任务
                  @scheduler.task('interval', id='job_1', args=(1,2),seconds=5)
                  def job1(a, b):  # 运行的定时任务的函数
                      print(str(a) + ' ' + str(b))
              # 步骤三: 运行主类中启动框架
                  if __name__ == '__main__':
                      app = Flask(__name__)  # 实例化flask
                      scheduler.start()  # 启动任务列表
                      app.debug=True
                      app.run(host='0.0.0.0',port= 8000)  # 启动 flask
    3. 使用方式三: 使用api
             # 步骤一: 定义后台线程中运行的调度器
                  from apscheduler.schedulers.background import BackgroundScheduler
                  # 调度器在后台线程中运行,不会阻塞当前线程
                  scheduler = BackgroundScheduler()
              # 步骤二: 定义定时任务函数
                  def job1(a, b):
                      print(str(a) + ' ' + str(b))
              # 步骤三: 使用API纳管
                  scheduler.scheduled_job(func=job1, args=("1","2"),id="job_1", trigger="interval", seconds=5, replace_existing=False)
                  '''
                  func:定时任务执行的函数名称。
                  args:任务执行函数的位置参数,若无参数可不填
                  id:任务id,唯一标识,修改,删除均以任务id作为标识
                  trigger:触发器类型,参数可选:date、interval、cron
                  replace_existing:将任务持久化至数据库中时,此参数必须添加,值为True。并且id值必须有。不然当程序重新启动时,任务会被重复添加。
                  '''
              # 步骤四: 启动定时框架
                  if __name__ == '__main__':
                      app = Flask(__name__
                      scheduler.start()
                      app.debug=True
                      app.run(host='0.0.0.0',port= 8000)
      
              # 实例对象 scheduler 拥有增、删、改、查等基本用法:
                  新增任务:add_job()
                  编辑任务:modify_job()
                  删除任务:remove_job(id)(删除所有任务:remove_all_jobs())
                  查询任务:get_job(id)(查询所有任务:get_jobs())
                  暂停任务:pause_job(id)
                  恢复任务:resume_job(id)
                  运行任务:run_job(id)(立即运行,无视任务设置的时间规则)
  2. 四个基础模块
    1. 任务调度器
        Apscheduler提供的调度器有7种:
                  BlockingScheduler : 调度器在当前进程的主线程中运行,会阻塞当前线程。
                  BackgroundScheduler : 调度器在后台线程中运行,不会阻塞当前线程。
                  AsyncIOScheduler : 结合 asyncio 模块(一个异步框架)一起使用。
                  GeventScheduler : 程序中使用 gevent(高性能的Python并发框架)作为IO模型,和 GeventExecutor 配合使用。
                  TornadoScheduler : 程序中使用 Tornado(一个web框架)的IO模型,用 ioloop.add_timeout 完成定时唤醒。
                  TwistedScheduler : 配合 TwistedExecutor,用 reactor.callLater 完成定时唤醒。
                  QtScheduler : Qt 应用,需使用QTimer完成定时唤醒。
      
              from apscheduler.schedulers.background import BackgroundScheduler,BlockingScheduler
              # 调度器在后台线程中运行,不会阻塞当前线程
              scheduler = BackgroundScheduler()
              # 调度器在当前进程的主线程中运行,会阻塞当前线程
              # scheduler = BlockingScheduler()
    2. 任务执行器
      用于设置线程池、进程池、协程池等,Apscheduler提供的执行器有6种:
                  ThreadPoolExecutor: 线程池执行器。
                  ProcessPoolExecutor: 进程池执行器。
                  GeventExecutor: Gevent程序执行器。
                  TornadoExecutor: Tornado程序执行器。
                  TwistedExecutor: Twisted程序执行器。
                  AsyncIOExecutor: asyncio程序执行器。
      
              from apscheduler.schedulers.background import BackgroundScheduler
              from apscheduler.executors.pool import ThreadPoolExecutor,ProcessPoolExecutor
              # 配置线程池,支持最多5个线程同时执行
              executors = {'default': ThreadPoolExecutor(5)}
              # 配置进程池,支持最多5个进程同时执行
              # executors = {'default': ProcessPoolExecutor(5)}
      
          # 创建类,导入配置
              scheduler = BackgroundScheduler(executors=executors)
      #### 任务配置
          # 任务相关配置
          defaults = {
              # 不合并执行
              'coalesce': False,
              # 同一时间同个任务最大执行次数为3
              'max_instances': 3,
              # 任务错过当前时间60s内,仍然可以触发任务
              'misfire_grace_time':60
          }
          # 创建类,导入配置
          scheduler = BackgroundScheduler(job_defaults=defaults)
    3. 任务存储器
       任务默认是存储在内存里的,服务重启后,内存里的任务会丢失。将任务保存在数据库中,每次启动会读取数据库的信息,可以避免服务重启丢失信息的问题。
              from flask import Flask
              from apscheduler.schedulers.background import BackgroundScheduler
      
              # 数据持久化至Mysql,默认table名为apscheduler_jobs
              from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
              jobstores = {'default': SQLAlchemyJobStore(url="mysql+pymysql://root:123456@127.0.0.1:3306/work")}
      
              # 数据持久化至MongoDB
              from apscheduler.jobstores.mongodb import MongoDBJobStore
              jobstores = {'default': MongoDBJobStore(host="127.0.0.1",port=27017, database="TEST", collection="jobs")}
      
              # 数据持久化至redis
              from apscheduler.jobstores.redis import RedisJobStore
              jobstores = {'default': RedisJobStore(host="127.0.0.1",port=6379, db=0)}
      
              # 引入配置的方法,在创建类时加入配置项
              scheduler = BackgroundScheduler(jobstores=jobstores)
              def job1(a, b):  # 运行的定时任务的函数
                  print(str(a) + ' ' + str(b))
      
              scheduler.add_job(func=job1, args=("1", "2"), id="job_1", trigger="interval", seconds=5, replace_existing=True)
              if __name__ == '__main__':
                  app = Flask(__name__)  # 实例化flask
                  scheduler.start()  # 启动任务列表
                  app.debug = True
                  app.run(host='0.0.0.0', port=8000)  # 启动 flask
    4. 任务触发器
      当你开始定时任务时,需要为定时策略选择一个触发器(设置  class Config 中 trigger 的值)。flask_apscheduler 提供了三种类型的触发器。
              date  一次性指定固定时间,只执行一次
              interval   间隔调度,隔多长时间执行一次
              cron  指定相对时间执行,比如:每月1号、每星期一执行
      #### 1. date  最基本的一种调度,指定固定时间,只执行一次
          run_date(str)– 精确时间
              class Config(object):
                  JOBS = [
                      {
                          'id': 'job1',
                          'func': '__main__:job1',
                          'args': (1, 2),
                          'trigger': 'date',                        # 指定任务触发器 date
                          'run_date': '2020-7-23 16:50:00'          # 指定时间 2020-7-23 16:50:00 执行
                      }
                  ]
                  SCHEDULER_API_ENABLED = True
      #### 2. interval  通过设置 时间间隔 来运行定时任务
              weeks (int) – 间隔几周
              days (int) – 间隔几天
              hours (int) – 间隔几小时
              minutes (int) – 间隔几分钟
              seconds (int) – 间隔多少秒
              start_date (datetime|str) – 开始日期
              end_date (datetime|str) – 结束日期
      
              class Config(object):
                  JOBS = [
                      {
                          'id': 'job1',
                          'func': '__main__:job1',
                          'args': (1, 2),
                          'trigger': 'interval',                        # 指定任务触发器 interval
                          'hours': 5                                     # 每间隔5h执行
                      }
                  ]
                  SCHEDULER_API_ENABLED = True
      
      #### 3. cron 通过设置 相对时间 来运行定时任务
              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) – 最晚结束时间(包含)
      
              class Config(object):
                  JOBS = [
                      {
                          'id': 'job1',
                          'func': '__main__:job1',
                          'args': (1, 2),
                          'trigger': 'cron',                            # 指定任务触发器 cron
                          'day_of_week': 'mon-fri',              # 每周1至周5早上6点执行
                          'hour': 6,
                          'minute': 00
                      }
                  ]
          SCHEDULER_API_ENABLED = True
      
      ### 4. 设置时区
          开发好定时脚本后部署到 K8S,发现报错 Timezone offset does not match system offset: 0 != 28800. Please, check your config files.
          本地运行好好的,为什么服务器上就报错了呢?
          原因是系统的时区和代码运行的时区不一致导致的。解决方法是在初始化 APScheduler() 的时候加上时区:BackgroundScheduler(timezone="Asia/Shanghai")
              '''...'''
              from apscheduler.schedulers.background import BackgroundScheduler
      
              class config:
                  JOBS = ['''...''']
                  SCHEDULER_TIMEZONE = 'Asia/Shanghai'
      
              '''...'''
      
              if __name__ == '__main__':
                  scheduler = APScheduler(BackgroundScheduler(timezone="Asia/Shanghai"))
                  scheduler.init_app(app)
                  scheduler.start()
                  app.run() 
posted @ 2023-05-15 11:21  521pingguo1314  阅读(1259)  评论(0)    收藏  举报