APScheduler是基於Quartz的一個Python定時任務框架,實現了Quartz的全部功能,使用起來十分方便。提供了基於日期、固定時間間隔以及crontab類型的任務,而且能夠持久化任務。基於這些功能,咱們能夠很方便的實現一個python定時任務系統,寫python仍是要比java舒服多了。java
1. 安裝python
安裝過程很簡單,能夠基於easy_install和源碼。web
[plain] view plain copy print?mongodb
easy_install apscheduler 數據庫
或者下載源碼,運行命令:併發
[plain] view plain copy print?框架
python setup.py install 函數
2. cron job例子spa
APScheduler是進程內的調度器,能夠定時觸發具體的函數,而且能夠訪問應用的全部變量和函數。在web應用中經過APScheduler實現定時任務是很方便的。下面看例子:線程
[python] view plain copy print?
from apscheduler.scheduler import Scheduler
schedudler = Scheduler(daemonic = False)
@schedudler.cron_schedule(second='*', day_of_week='0-4', hour='9-12,13-15')
def quote_send_sh_job():
print 'a simple cron job start at', datetime.datetime.now()
schedudler.start()
上面經過裝飾器定義了cron job,能夠經過函數scheduler.add_cron_job添加,用裝飾器更方便。Scheduler構造函數中傳入daemonic參數,表示執行線程是非守護的,在Schduler的文檔中推薦使用非守護線程:
[plain] view plain copy print?
Jobs are always executed in non-daemonic threads.
具體cron job的配置參看doc,基本上與Quartz一致。
在添加job時還有一個比較重要的參數max_instances,指定一個job的併發實例數,默認值是1。默認狀況下,若是一個job準備執行,可是該job的前一個實例還沒有執行完,則後一個job會失敗,能夠經過這個參數來改變這種狀況。
3. Store
APScheduler提供了jobstore用於存儲job的執行信息,默認使用的是RAMJobStore,還提供了SQLAlchemyJobStore、ShelveJobStore和MongoDBJobStore。APScheduler容許同時使用多個jobstore,經過別名(alias)區分,在添加job時須要指定具體的jobstore的別名,不然使用的是別名是default的jobstore,即RAMJobStore。下面以MongoDBJobStore舉例說明。
[python] view plain copy print?
import pymongo
from apscheduler.scheduler import Scheduler
from apscheduler.jobstores.mongodb_store import MongoDBJobStore
import time
sched = Scheduler(daemonic = False)
mongo = pymongo.Connection(host='127.0.0.1', port=27017)
store = MongoDBJobStore(connection=mongo)
sched.add_jobstore(store, 'mongo') # 別名是mongo
@sched.cron_schedule(second='*', day_of_week='0-4', hour='9-12,13-15', jobstore='mongo') # 向別名爲mongo的jobstore添加job
def job():
print 'a job'
time.sleep(1)
sched.start()
注意start必須在添加job動做以後調用,不然會拋錯。默認會把job信息保存在apscheduler數據庫下的jobs表:
[plain] view plain copy print?
> db.jobs.findOne()
{
"_id" : ObjectId("502202d1443c1557fa8b8d66"),
"runs" : 20,
"name" : "job",
"misfire_grace_time" : 1,
"coalesce" : true,
"args" : BinData(0,"gAJdcQEu"),
"next_run_time" : ISODate("2012-08-08T14:10:46Z"),
"max_instances" : 1,
"max_runs" : null,
"trigger" : BinData(0,"gAJjYXBzY2hlZHVsZXIudHJpZ2dlcnMuY3JvbgpDcm9uVHJpZ2dlcgpxASmBcQJ9cQMoVQZmaWVsZHNxBF1xBShjYXBzY2hlZHVsZXIudHJpZ2dlcnMuY3Jvbi5maWVsZHMKQmFzZUZpZWxkCnEGKYFxB31xCChVCmlzX2RlZmF1bHRxCYhVC2V4cHJlc3Npb25zcQpdcQtjYXBzY2hlZHVsZXIudHJpZ2dlcnMuY3Jvbi5leHByZXNzaW9ucwpBbGxFeHByZXNzaW9uCnEMKYFxDX1xDlUEc3RlcHEPTnNiYVUEbmFtZXEQVQR5ZWFycRF1YmgGKYFxEn1xEyhoCYhoCl1xFGgMKYFxFX1xFmgPTnNiYWgQVQVtb250aHEXdWJjYXBzY2hlZHVsZXIudHJpZ2dlcnMuY3Jvbi5maWVsZHMKRGF5T2ZNb250aEZpZWxkCnEYKYFxGX1xGihoCYhoCl1xG2gMKYFxHH1xHWgPTnNiYWgQVQNkYXlxHnViY2Fwc2NoZWR1bGVyLnRyaWdnZXJzLmNyb24uZmllbGRzCldlZWtGaWVsZApxHymBcSB9cSEoaAmIaApdcSJoDCmBcSN9cSRoD05zYmFoEFUEd2Vla3EldWJjYXBzY2hlZHVsZXIudHJpZ2dlcnMuY3Jvbi5maWVsZHMKRGF5T2ZXZWVrRmllbGQKcSYpgXEnfXEoKGgJiWgKXXEpY2Fwc2NoZWR1bGVyLnRyaWdnZXJzLmNyb24uZXhwcmVzc2lvbnMKUmFuZ2VFeHByZXNzaW9uCnEqKYFxK31xLChoD05VBGxhc3RxLUsEVQVmaXJzdHEuSwB1YmFoEFULZGF5X29mX3dlZWtxL3ViaAYpgXEwfXExKGgJiWgKXXEyKGgqKYFxM31xNChoD05oLUsMaC5LCXViaCopgXE1fXE2KGgPTmgtSw9oLksNdWJlaBBVBGhvdXJxN3ViaAYpgXE4fXE5KGgJiGgKXXE6aAwpgXE7fXE8aA9Oc2JhaBBVBm1pbnV0ZXE9dWJoBimBcT59cT8oaAmJaApdcUBoDCmBcUF9cUJoD05zYmFoEFUGc2Vjb25kcUN1YmVVCnN0YXJ0X2RhdGVxRE51Yi4="),
"func_ref" : "__main__:job",
"kwargs" : BinData(0,"gAJ9cQEu")
}
上面就是存儲的具體信息。
4.異常處理
當job拋出異常時,APScheduler會默默的把他吞掉,不提供任何提示,這不是一種好的實踐,咱們必須知曉程序的任何差錯。APScheduler提供註冊listener,能夠監聽一些事件,包括:job拋出異常、job沒有來得及執行等。
Constant Event class Triggered when...
EVENT_SCHEDULER_START SchedulerEvent The scheduler is started
EVENT_SCHEDULER_SHUTDOWN SchedulerEvent The scheduler is shut down
EVENT_JOBSTORE_ADDED JobStoreEvent A job store is added to the scheduler
EVENT_JOBSTORE_REMOVED JobStoreEvent A job store is removed from the scheduler
EVENT_JOBSTORE_JOB_ADDED JobStoreEvent A job is added to a job store
EVENT_JOBSTORE_JOB_REMOVED JobStoreEvent A job is removed from a job store
EVENT_JOB_EXECUTED JobEvent A job is executed successfully
EVENT_JOB_ERROR JobEvent A job raised an exception during execution
EVENT_JOB_MISSED JobEvent A job’s execution time is missed
看下面的例子,監聽異常和miss事件,這裏用logging模塊打印日誌,logger.exception()能夠打印出異常堆棧信息。
[python] view plain copy print?
def err_listener(ev):
err_logger = logging.getLogger('schedErrJob')
if ev.exception:
err_logger.exception('%s error.', str(ev.job))
else:
err_logger.info('%s miss', str(ev.job))
schedudler.add_listener(err_listener, apscheduler.events.EVENT_JOB_ERROR | apscheduler.events.EVENT_JOB_MISSED)
事件的屬性包括:
job – the job instance in question
scheduled_run_time – the time when the job was scheduled to be run
retval – the return value of the successfully executed job
exception – the exception raised by the job
traceback – the traceback object associated with the exception
最後,須要注意一點當job不以daemon模式運行時,而且APScheduler也不是daemon的,那麼在關閉腳本時,Ctrl + C是不奏效的,必須kill才能夠。能夠經過命令實現關閉腳本:
[plain] view plain copy print?
ps axu | grep {腳本名} | grep -v grep | awk '{print $2;}' | xargs kill