原文鏈接: https://www.cnblogs.com/zhaoyingjie/p/9664081.html
APScheduler(Python化的Cron)使用總結 定時任務
APScheduler(Python化的Cron)使用總結
簡介
APScheduler全程為Advanced Python Scheduler,是一款輕量級的Python任務調度框架。它允許你像Cron那樣安排定期執行的任務,並且支持Python函數或任意可調用的對象。官方文檔:https://apscheduler.readthedocs.io/en/latest/userguide.html#basic-concepts
APScheduler安裝
方法一:使用pip安裝
$ pip install apscheduler
方法二:如果pip不起作用,可以從pypi上下載最新的源碼包(https://pypi.python.org/pypi/APScheduler/)進行安裝:
$ python setup.py install
APScheduler組件
triggers(觸發器): 觸發器中包含調度邏輯,每個作業都由自己的觸發器來決定下次運行時間。除了他們自己初始配置意外,觸發器完全是無狀態的。
job stores(作業存儲器):存儲被調度的作業,默認的作業存儲器只是簡單地把作業保存在內存中,其他的作業存儲器則是將作業保存在數據庫中。當作業被保存到一個持久化的作業存儲器中的時候,該作業的數據會被序列化,並在加載時被反序列化。作業存儲器不能共享調度器。
executors(執行器):處理作業的運行,他們通常通過在作業中提交指定的可調用對象到一個線程或者進城池來進行。當作業完成時,執行器將會通知調度器。
schedulers(調度器):配置作業存儲器和執行器可以在調度器中完成,例如添加、修改和移除作業。根據不同的應用場景可以選用不同的調度器,可選的有BlockingScheduler,BackgroundScheduler,AsyncIOScheduler,GeventScheduler,TornadoScheduler,TwistedScheduler,QtScheduler 7種。
調度器
BlockingScheduler : 當調度器是你應用中唯一要運行的東西時。
BackgroundScheduler : 當你沒有運行任何其他框架並希望調度器在你應用的后台執行時使用(充電樁即使用此種方式)。
AsyncIOScheduler : 當你的程序使用了asyncio(一個異步框架)的時候使用。
GeventScheduler : 當你的程序使用了gevent(高性能的Python並發框架)的時候使用。
TornadoScheduler : 當你的程序基於Tornado(一個web框架)的時候使用。
TwistedScheduler : 當你的程序使用了Twisted(一個異步框架)的時候使用
QtScheduler : 如果你的應用是一個Qt應用的時候可以使用。
作業存儲器
如果你的應用在每次啟動的時候都會重新創建作業,那么使用默認的作業存儲器(MemoryJobStore)即可,但是如果你需要在調度器重啟或者應用程序奔潰的情況下任然保留作業,你應該根據你的應用環境來選擇具體的作業存儲器。例如:使用Mongo或者SQLAlchemy JobStore (用於支持大多數RDBMS)
執行器
對執行器的選擇取決於你使用上面哪些框架,大多數情況下,使用默認的ThreadPoolExecutor已經能夠滿足需求。如果你的應用涉及到CPU密集型操作,你可以考慮使用ProcessPoolExecutor來使用更多的CPU核心。你也可以同時使用兩者,將ProcessPoolExecutor作為第二執行器。
觸發器
當你調度作業的時候,你需要為這個作業選擇一個觸發器,用來描述這個作業何時被觸發,APScheduler有三種內置的觸發器類型:
date 一次性指定日期
interval 在某個時間范圍內間隔多長時間執行一次
cron 和Linux crontab格式兼容,最為強大
date
最基本的一種調度,作業只會執行一次。它的參數如下:
run_date (datetime|str) – 作業的運行日期或時間
timezone (datetime.tzinfo|str) – 指定時區
舉個栗子:
# 2016-12-12運行一次job_function sched.add_job(job_function, 'date', run_date=date(2016, 12, 12), args=['text']) # 2016-12-12 12:00:00運行一次job_function sched.add_job(job_function, 'date', run_date=datetime(2016, 12, 12, 12, 0, 0), args=['text']) interval
間隔調度,參數如下:
weeks (int) – 間隔幾周
days (int) – 間隔幾天
hours (int) – 間隔幾小時
minutes (int) – 間隔幾分鍾
seconds (int) – 間隔多少秒
start_date (datetime|str) – 開始日期
end_date (datetime|str) – 結束日期
timezone (datetime.tzinfo|str) – 時區
舉個栗子:
# 每兩個小時調一下job_function sched.add_job(job_function, 'interval', hours=2) 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) – 最晚結束時間(包含)
timezone (datetime.tzinfo|str) – 指定時區
舉個栗子:
# job_function將會在6,7,8,11,12月的第3個周五的1,2,3點運行 sched.add_job(job_function, 'cron', month='6-8,11-12', day='3rd fri', hour='0-3') # 截止到2016-12-30 00:00:00,每周一到周五早上五點半運行job_function sched.add_job(job_function, 'cron', day_of_week='mon-fri', hour=5, minute=30, end_date='2016-12-31')
配置調度程序
在應用程序中使用默認作業存儲和默認執行程序運行BackgroundScheduler的例子:
from apscheduler.schedulers.background import BackgroundScheduler scheduler = BackgroundScheduler() # Initialize the rest of the application here, or before the scheduler initialization
這將生成一個名為“default”的MemoryJobStore和名為“default”的ThreadPoolExecutor的BackgroundScheduler,默認最大線程數為10。
如果不滿足於當前配置,如希望使用兩個執行器有兩個作業存儲器,並且還想要調整新作業的默認值並設置不同的時區,可按如下配置:
from pytz import utc from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.jobstores.mongodb import MongoDBJobStore from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor # 配置作業存儲器 jobstores = { 'mongo': MongoDBJobStore(), 'default': SQLAlchemyJobStore(url='sqlite:///jobs.sqlite') } # 配置執行器,並設置線程數 executors = { 'default': ThreadPoolExecutor(20), 'processpool': ProcessPoolExecutor(5) } job_defaults = { 'coalesce': False, # 默認情況下關閉新的作業 'max_instances': 3 # 設置調度程序將同時運行的特定作業的最大實例數3 } scheduler = BackgroundScheduler(jobstores=jobstores, executors=executors, job_defaults=job_defaults, timezone=utc)
啟動調度器
啟動調度器只需要調用start()方法,對於除BlockingScheduler以外的調度程序,此調用將立即返回,您可以繼續應用程序的初始化過程,可能會將作業添加到調度程序。
對於BlockingScheduler,只需在完成初始化步驟后調用start()
scheduler.start()
添加作業
方法一:調用add_job()方法
最常見的方法,add_job()方法返回一個apscheduler.job.Job實例,您可以稍后使用它來修改或刪除該作業。
方法二:使用裝飾器scheduled_job()
此方法主要是方便的聲明在應用程序運行時不會改變的作業
刪除作業
方法一:通過作業ID或別名調用remove_job()刪除作業
方法二:通過add_job()返回的job實例調用remove()方法刪除作業
舉個栗子:
# 實例刪除 job = scheduler.add_job(myfunc, 'interval', minutes=2) job.remove() # id刪除 scheduler.add_job(myfunc, 'interval', minutes=2, id='my_job_id') scheduler.remove_job('my_job_id')
暫停和恢復作業
可以通過Job實例或調度程序本身輕松暫停和恢復作業。 當作業暫停時,下一個運行時間將被清除,直到作業恢復,不會再計算運行時間。 要暫停作業,請使用以下任一方法:
apscheduler.job.Job.pause() apscheduler.schedulers.base.BaseScheduler.pause_job()
恢復作業:
apscheduler.job.Job.resume() apscheduler.schedulers.base.BaseScheduler.resume_job()
獲取作業列表
要獲得計划作業的機器可處理列表,可以使用get_jobs()方法。 它將返回一個Job實例列表。 如果您只對特定作業存儲中包含的作業感興趣,則將作業存儲別名作為第二個參數。
為了方便起見,可以使用print_jobs()方法,它將打印格式化的作業列表,觸發器和下次運行時間。
修改作業屬性
您可以通過調用apscheduler.job.Job.modify()或modify_job()來修改除id以外的任何作業屬性。
job.modify(max_instances=6, name='Alternate name')
關閉調度程序
默認情況下,調度程序關閉其作業存儲和執行程序,並等待所有當前正在執行的作業完成,wait=False參數可選,代表立即停止,不用等待。
scheduler.shutdown(wait=False)
附:1、定時任務運行腳本小例子:
import datetime from apscheduler.schedulers.blocking import BlockingScheduler from app.untils.log_builder import sys_logging scheduler = BlockingScheduler() # 后台運行 # 設置為每日凌晨00:30:30時執行一次調度程序 @scheduler.scheduled_job("cron", day_of_week='*', hour='1', minute='30', second='30') def rebate(): print "schedule execute" sys_logging.debug("statistic scheduler execute success" + datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) if __name__ == '__main__': try: scheduler.start() sys_logging.debug("statistic scheduler start success") except (KeyboardInterrupt, SystemExit): scheduler.shutdown() sys_logging.debug("statistic scheduler start-up fail")
2、第一次使用此定時器時總會執行兩次,一直不知道為什么,后來發現,python 的flask框架在debug模式下會多開一個線程監測項目變化,所以每次會跑兩遍,可以將debug選項改為False