APScheduler定時任務框架的使用


前言

APScheduler基於Quartz的一個Python定時任務框架,實現了Quartz的所有功能,使用起來十分方便。提供了基於日期、固定時間間隔以及crontab類型的任務,不僅可以添加、刪除定時任務,還可以將任務存儲到數據庫中、實現任務的持久化。基於這些功能,我們可以很方便的實現一個python定時任務系統。

安裝

1、利用pip進行安裝

pip install apscheduler

2、 APScheduler有四種組成部分:

triggers(觸發器):
  觸發器包含調度邏輯,每一個作業有它自己的觸發器,用於決定接下來哪一個作業會運行,除了他們自己初始化配置外,觸發器完全是無狀態的。
job stores(作業存儲):
  用來存儲被調度的作業,默認的作業存儲器是簡單地把作業任務保存在內存中,其它作業存儲器可以將任務作業保存到各種數據庫中,支持MongoDB、Redis、SQLAlchemy存儲方式。當對作業任務進行持久化存儲的時候,作業的數據將被序列化,重新讀取作業時在反序列化。
executors(執行器):
  執行器用來執行定時任務,只是將需要執行的任務放在新的線程或者線程池中運行。當作業任務完成時,執行器將會通知調度器。對於執行器,默認情況下選擇ThreadPoolExecutor就可以了,但是如果涉及到一下特殊任務如比較消耗CPU的任務則可以選擇ProcessPoolExecutor,當然根據根據實際需求可以同時使用兩種執行器。
schedulers(調度器):
  調度器是將其它部分聯系在一起,一般在應用程序中只有一個調度器,應用開發者不會直接操作觸發器、任務存儲以及執行器,相反調度器提供了處理的接口。通過調度器完成任務的存儲以及執行器的配置操作,如可以添加。修改、移除任務作業。
 

3、 APScheduler提供了七種調度器:

BlockingScheduler適合於只在進程中運行單個任務的情況,通常在調度器是你唯一要運行的東西時使用。
BackgroundScheduler: 適合於要求任何在程序后台運行的情況,當希望調度器在應用后台執行時使用。
AsyncIOScheduler適合於使用asyncio異步框架的情況
GeventScheduler: 適合於使用gevent框架的情況
TornadoScheduler: 適合於使用Tornado框架的應用
TwistedScheduler: 適合使用Twisted框架的應用
QtScheduler: 適合使用QT的情況

4、APScheduler提供了四種存儲方式:

MemoryJobStore
sqlalchemy
mongodb
redis

5、APScheduler提供了三種任務觸發器:

data:固定日期觸發器:任務只運行一次,運行完畢自動清除;若錯過指定運行時間,任務不會被創建
interval:時間間隔觸發器,每隔多長時間觸發一次
cron:cron風格的任務觸發 ,可以每天早上固定時間點執行一次任務

 (5.1)data

固定時間調度(作業只會執行一次)

import time
from apscheduler.schedulers.blocking import BlockingScheduler

def my_job():
    print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))
sched = BlockingScheduler()
## 采用dete固定時間模式,在特定時間只執行一次
sched.add_job(my_job, 'date', run_date='2019-01-01 00:00:00)
sched.start()

(5.2)interval

例如每隔五秒執行一次:

import time
from apscheduler.schedulers.blocking import BlockingScheduler

def my_job():
    print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))
#### 采用interval固定間隔模式,每隔五秒只執行一次
sched.add_job(my_job, 'interval', seconds=5)
sched.start()

間隔調度,參數如下:

weeks (int)  –  間隔幾周 
days (int)  –  間隔幾天 
hours (int)  –  間隔幾小時 
minutes (int)  –  間隔幾分鍾 
seconds (int)  –  間隔多少秒 
start_date (datetime|str)  –  開始日期 
end_date (datetime|str)  –  結束日期 
timezone (datetime.tzinfo|str)  –  時區 

(5.3)cron

定時調度(例如在每一天上午八點半或者12點半執行任務)

import time
from apscheduler.schedulers.blocking import BlockingScheduler

scheduler = BlockingScheduler()

def everyday_crawler_job():
    print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))
    # subprocess.call("python Crawler.py")

sched = BlockingScheduler()
#每隔一天 執行抓包程序
# sched.add_job(everyday_crawler_job, 'interval', days=1)days
#每天早上八點半和十二點半各執行一次抓包程序
sched.add_job(everyday_crawler_job, 'cron', hour='8, 12', minute='30')
sched.start()

參數如下:

(int|str) 表示參數既可以是int類型,也可以是str類型
(datetime | str) 表示參數既可以是datetime類型,也可以是str類型
year (int|str) – 4-digit year -(表示四位數的年份,如2008年)
month (int|str) – month (1-12) -(表示取值范圍為1-12月)
day (int|str) – day of the (1-31) -(表示取值范圍為1-31日)
week (int|str) – ISO week (1-53) -(格里歷2006年12月31日可以寫成2006年-W52-7(擴展形式)或2006W527(緊湊形式))
day_of_week (int|str) – number or name of weekday (0-6 or mon,tue,wed,thu,fri,sat,sun) - (表示一周中的第幾天,既可以用0-6表示也可以用其英語縮寫表示)
hour (int|str) – hour (0-23) - (表示取值范圍為0-23時)
minute (int|str) – minute (0-59) - (表示取值范圍為0-59分)
second (int|str) – second (0-59) - (表示取值范圍為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) -(表示時區取值)

cron其他參數格式用法示例如下:

#表示2017年3月22日17時19分07秒執行該程序
sched.add_job(my_job, 'cron', year=2017,month = 03,day = 22,hour = 17,minute = 19,second = 07)
 
#表示任務在6,7,8,11,12月份的第三個星期五的00:00,01:00,02:00,03:00 執行該程序
sched.add_job(my_job, 'cron', month='6-8,11-12', day='3rd fri', hour='0-3')
 
#表示從星期一到星期五5:30(AM)直到2014-05-30 00:00:00
sched.add_job(my_job(), 'cron', day_of_week='mon-fri', hour=5, minute=30,end_date='2014-05-30')
 
#表示每5秒執行該程序一次,相當於interval 間隔調度中seconds = 5
sched.add_job(my_job, 'cron',second = '*/5')

在設置定時調度任務時遇到一個問題,定時任務未執行打印的log如下:

Run time of job "everyday_crawler_job (trigger: cron[hour='8,12', minute='30'], next run at: 2019-01-30 08:30:00 CST)" was missed by 0:00:01.084138
這個log的意思是:距離下次運行時間,錯過了1秒,所有第二次就沒有執行任務
解決方法:
在add_job()中添加參數:
misfire_grace_time: 主要就是為了解決這個was missed by 這個報錯,添加允許容錯的時間,單位為:s
coalesce如果系統因某些原因沒有執行任務,導致任務累計,為True則只運行最后一次,為False 則累計的任務全部跑一遍

定時任務的停止

如果我們在終端中直接執行的話,關閉終端窗口,Python任務就會中斷,Python進程會被殺死,程序將停止運行。如果我們用編輯器直接運行python腳本,這樣執行后,如果未正確取消進程,關閉編輯器后,程序依舊運行。
 
如何停止呢,可使用如下方法:
如果知道進程id直接只用kill命令結束即可,例如:
進程id:3057
$ kill 3057

如果運行后忘記進程ID,則可遵循下面的方法進行停止

ps -e | grep python

這樣將會在終端列出python相關的進程:

$ ps -e | grep python
 1025 ??         0:00.41 
 1602 ??         0:00.37 
17699 ttys001    0:00.00 grep python

然后分別執行kill就可以了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM