定时任务--Python中的APScheduler的使用(基于Flask)

1.APScheduler的简介:

  • Advanced Python Scheduler(APScheduler)是一个Python库,可让您安排Python代码稍后执行,一次或定期执行。(定时任务工具)
  • 官方文档

2.APScheduler的特点:

①不依赖于linux的crontab,独立运行。
②可以作为动态添加定时任务。
③可以将添加的任务持久化保存。

3.APScheduler的组件:

  • 存储器(job stores)
    • 任务存储是安排任务存储在哪里。默认存储只是将任务保留在内存中,但也可以将它们存储在各种类型的数据库中(例如sqlite,mysql,redis等)。
  • 触发器(triggers)
    • 可以理解为任务什么时候执行。每个任务都有自己的触发器。除了初始配置之外,触发器完全是无状态的。
  • 执行器(executors)
    • 任务执行人是处理任务的运行。他们通常是将任务提交给线程或进程池来完成此操作。任务完成后,执行程序会通知调度程序,调度程序随后会发出相应的事件。
  • 调度器(schedulers)
    • 任务调度者是将任务存储(job stores),任务执行人(executors)绑定在一起,起到管理定时任务的作用。通常只在应用程序中运行一个调度程序。应用程序开发人员通常不直接处理作业存储,执行程序或触发器,一般都是通过修改配置信息来实现。配置作业存储和执行程序是通过调度程序完成的,添加,修改和删除任务由调度者管理。

4.安装(pip安装)

  • pip install apscheduler

5.Python中操作各个组件

  • 1.调度器(schedulers):
    • BlockingScheduler
      from apscheduler.schedulers.blocking import BlockingScheduler
      """
      BlockingScheduler是阻塞模式,即运行到start()时,阻塞
      """
      scheduler = BlockingScheduler()
      scheduler.start()
      
    • BackgroundScheduler
      from apscheduler.schedulers.background import BackgroundScheduler
      """
      BackgroundScheduler时后台运行模式,即运行到start()时,立即返回
      """
      scheduler = BackgroundScheduler()
      scheduler.start()
      
  • 2.执行器(executors):
    • ThreadPoolExecutor------(线程)
      from apscheduler.executors.pool import ThreadPoolExecutor
      from apscheduler.schedulers.background import BackgroundScheduler
      '''
      executor = ThreadPoolExecutor(max_workers=20)
      线程池,最多20个线程同时执行
      '''
      executors = {
          'default':ThreadPoolExecutor(max_workers=20)
      }
      scheduler = BackgroundScheduler(executors=executors)
      scheduler.start()
      
    • ProcessPoolExecutor------(进程)
      from apscheduler.executors.pool import ProcessPoolExecutor
      from apscheduler.schedulers.background import BackgroundScheduler
      '''
      executor = ProcessPoolExecutor(max_workers=10)
      进程池,最多10个进程同时执行
      '''
      executors = {
          'default':ProcessPoolExecutor(max_workers=10)
      }
      scheduler = BackgroundScheduler(executors=executors)
      scheduler.start()
      
  • 3.存储器(job stores):
    • 不需要持久存储,可以存入内存中(MemoryJobStore)
      from apscheduler.jobstores.memory import MemoryJobStore
      from apscheduler.schedulers.background import BackgroundScheduler
      """
      MemoryJobStore是存储在内存中,不提供持久化存储。
      """
      jobstores = {
          'default':MemoryJobStore()
      }
      scheduler = BackgroundScheduler(jobstores=jobstores)
      scheduler.start()
      
    • 需要持久存储,可以结合数据库(SQLAlchemyJobStore)
      from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
      from apscheduler.schedulers.background import BackgroundScheduler
      """
      SQLALchemyJobStore可以连接数据库,提供持久化存储。
      """
      jobstores = {
          'default':SQLAlchemyJobStore(url='sqlite:///demo.sqlite'),
          # 'default':SQLAlchemyJobStore(url='mysql://root:[email protected]:3306/test')
      }
      scheduler = BackgroundScheduler(jobstores=jobstores)
      scheduler.start()
      
    • 附上其他数据库配置连接(github)
  • 4.触发器(triggers):
    • date----(指定某个日期执行一次,或者某个时间执行一次)
      from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
      from apscheduler.executors.pool import ThreadPoolExecutor
      from apscheduler.schedulers.background import BackgroundScheduler
      from datetime import date, datetime
      
      jobstores = {
          # 'default':SQLAlchemyJobStore(url='mysql://root:[email protected]:3306/test')
          'default':SQLAlchemyJobStore(url='sqlite:///demo.sqlite')
      }
      
      executes = {
          'default':ThreadPoolExecutor(10)
      }
      
      def my_job():
          print('job1%s' % datetime.now())
      
      """
      出现Unable to determine the name of the local timezone错误
      
      rm -rf /etc/localtime
      ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
      # 如果你是CentOS7就更简单了,单单执行下面命令就OK了
      timedatectl set-timezone Asia/Shanghai
      """
      scheduler = BackgroundScheduler(jobstores=jobstores,executes=executes)
      # scheduler.add_job(my_job,'date',run_date=datetime(2019,11,26,20,49,30))
      scheduler.add_job(my_job,'date',run_date='2019-11-26 20:53:30')
      scheduler.start()
      
      while True:
          pass
      
    • interval----(经过指定的时间间隔执行)
      from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
      from apscheduler.executors.pool import ThreadPoolExecutor
      from apscheduler.schedulers.background import BackgroundScheduler
      from datetime import date, datetime
      
      """
      weeks(int)
      days(int)
      hours(int)
      minutes(int)
      seconds(int)
      start_date(datetime|str)
      end_date(datetime|str)
      timezone(datetime.tzinfo|str) 
      """
      jobstores = {
          'default': SQLAlchemyJobStore(url='sqlite:///demo.sqlite')
      }
      
      executes = {
          'default': ThreadPoolExecutor(10)
      }
      
      
      def my_job(p1, p2):
          print('{}----{}---%s'.format(p1, p2) % datetime.now())
      
      
      scheduler = BackgroundScheduler(jobstores=jobstores, executes=executes)
      # scheduler.add_job(my_job, 'interval', seconds=3, args=[10, 20])
      scheduler.add_job(my_job, 'interval', hours=3, args=[10, 20], start_date=datetime(2019, 1, 1, 0, 0, 0),
                        end_date=datetime(2019, 1, 2, 0, 0, 0))
      scheduler.start()
      
      while True:
          pass
      
    • cron----(按照指定的周期执行)
      from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
      from apscheduler.executors.pool import ThreadPoolExecutor
      from apscheduler.schedulers.background import BackgroundScheduler
      from datetime import date, datetime
      
      """
      year(int|str) – 4-digit year
      month(int|str) – month (1-12)
      day(int|str) – day of the (1-31)
      week(int|str) – ISO week (1-53)
      day_of_week(int|str) – number or name of weekday (0-6 or mon,tue,wed,thu,fri,sat,sun)
      hour(int|str) – hour (0-23)
      minute(int|str) – minute (0-59)
      second(int|str) – second (0-59)
      start_date(datetime|str) – earliest possible date/time to trigger on (inclusive)
      end_date(datetime|str) – latest possible date/time to trigger on (inclusive)
      timezone(datetime.tzinfo|str) – time zone to use for the date/time calculations (defaults to scheduler timezone)
      """
      jobstores = {
          'default': SQLAlchemyJobStore(url='sqlite:///demo.sqlite')
      }
      
      executes = {
          'default': ThreadPoolExecutor(10)
      }
      
      
      def my_job(p1, p2):
          print('{}----{}---%s'.format(p1, p2) % datetime.now())
      
      
      scheduler = BackgroundScheduler(jobstores=jobstores, executes=executes)
      # 在7、8、10、12月的第3个周五的00:00, 01:00, 02:00和03:00 执行
      scheduler.add_job(my_job,'cron',month='7-8,10-12',day='3rd fri',hour='0-3')
      # 在2019年12月30日前的周一到周五的5:30执行
      scheduler.add_job(my_job,'cron',day_of_week='mon-fri',hour=5,minute=30,end_date='2019-12-30')
      scheduler.add_job(my_job,'cron',day_of_week='mon-fri',end_date='2019-12-30 05:30:00')
      
      scheduler.start()
      
      while True:
          pass
      

6.对定时任务的操作(Flask)

from flask import Flask
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.executors.pool import ThreadPoolExecutor
from apscheduler.schedulers.background import BackgroundScheduler

app = Flask(__name__)

jobstores = {
    'default': SQLAlchemyJobStore(url='sqlite:///demo.sqlite')
}

executors = {
    'default': ThreadPoolExecutor(max_workers=10)
}

# 使用app对象接管Schedulers
app.schedulers = BackgroundScheduler(jobstores=jobstores, executors=executors)


# 首页
@app.route('/')
def index():
    return 'index'


# 定义任务
def my_job():
    print('job1')


# 开始任务
@app.route('/start')
def startjob():
    app.schedulers.add_job(my_job, 'interval', seconds=3, id='job1')
    app.schedulers.start()
    return 'start'


# 暂停任务
@app.route('/pause')
def pausejob():
    app.schedulers.pause()
    return 'pause'


# 恢复任务
@app.route('/resume')
def resumejob():
    app.schedulers.resume()
    return 'resume'


# 删除任务
@app.route('/remove')
def removejob():
    app.schedulers.remove_job('job1')
    return 'remove'

if __name__ == '__main__':
	# 不定义host,默认使用127.0.0.1:5000
    app.run(host='192.168.179.131')

7.由于自己也在学习过程中,代码是基础代码,有不足之处,请各位指出。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章