定時任務--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.由於自己也在學習過程中,代碼是基礎代碼,有不足之處,請各位指出。

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