APScheduler+MySQL實(shí)現(xiàn)定時(shí)任務(wù)及其持久化存儲(chǔ)

最近,想要實(shí)現(xiàn)一個(gè)功能,就是添加定時(shí)任務(wù)的同時(shí)記錄其任務(wù)信息到數(shù)據(jù)庫中胰坟,可以通過接口查看設(shè)定了哪些定時(shí)任務(wù),經(jīng)過調(diào)研泞辐,發(fā)現(xiàn)大家公認(rèn)的Python最好用的定時(shí)任務(wù)框架是APScheduler笔横。

Python Scheduler(APScheduler)是一個(gè)Python庫竞滓,它允許您安排稍后要執(zhí)行的Python代碼,只需一次或定期執(zhí)行吹缔。 您可以在您的同時(shí)添加新的作業(yè)或刪除舊的舊作業(yè)商佑。 如果在數(shù)據(jù)庫中存儲(chǔ)工作,他們還將存活調(diào)度程序重新啟動(dòng)并保持狀態(tài)厢塘。 調(diào)度程序重新啟動(dòng)時(shí)茶没,它將運(yùn)行它在脫機(jī)時(shí)應(yīng)該運(yùn)行的所有作業(yè)

在網(wǎng)上找了一堆資料,包括官方教程晚碾,但對(duì)于和MySQL協(xié)作使用的方面語焉不詳抓半,因此,這里做個(gè)記錄格嘁。

本文參考了官方教程以及大佬1的博客笛求、大佬2的博客

項(xiàng)目使用的環(huán)境如下:

  • Python 3.7
  • MySQL
  • APScheduler
  • Navicat for MySQL

APScheduler Startup

首先,安裝APScheduler:

pip install apscheduler

然后就可以編寫簡(jiǎn)單的demo了:

from apscheduler.schedulers.blocking import BlockingScheduler
from datetime import datetime

def job():
    # 輸出當(dāng)前時(shí)間
    print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))

# BlockingScheduler
scheduler = BlockingScheduler()
scheduler.add_job(job, 'cron', day_of_week='0-4', hour=6, minute=30)

這個(gè)demo表示每周的星期一到星期五的六點(diǎn)半報(bào)時(shí)

APScheduler基礎(chǔ)教程

具體見大佬2的博客讥蔽,這里不做贅述

這里總結(jié)一下常用的任務(wù)模式。

interval間隔時(shí)間任務(wù)

即每隔一段時(shí)間執(zhí)行一次画机,可能的字段為:

字段 值類型 說明
weeks int number of weeks to wait
days int number of days to wait
hours int number of hours to wait
minutes int number of minutes to wait
seconds int number of seconds to wait
start_date datetime/str starting point for the interval calculation
end_date datetime/str latest possible date/time to trigger on
timezone datetime.tzinfo/str time zone to use for the date/time calculations

例子:

#表示每隔3秒執(zhí)行一次任務(wù)
scheduler.add_job(tok, 'interval', seconds=3)

#表示每隔3天17時(shí)19分07秒執(zhí)行一次任務(wù)
sched.add_job(my_job, 'interval',days  = 03,hours = 17,minutes = 19,seconds = 07)

date定點(diǎn)任務(wù)

即在某個(gè)時(shí)刻運(yùn)行冶伞,但僅執(zhí)行一次,可能的字段為:

字段 值類型 說明
run_date datetime/str the date/time to run the job at -(任務(wù)開始的時(shí)間)
timezone datetime.tzinfo/str time zone for run_date if it doesn’t have one already

栗子:

# 任務(wù)將在2009年11月6日00:00:00執(zhí)行
sched.add_job(my_job, 'date', run_date=date(2009, 11, 6), args=['text'])

# 任務(wù)將在2009年11月6日16:30:05執(zhí)行
sched.add_job(my_job, 'date', run_date=datetime(2009, 11, 6, 16, 30, 5), args=['text'])

cron某一時(shí)刻任務(wù)

可能的字段為:

字段 值類型 說明
year int/str XXXX 表示四位數(shù)的年份步氏,如2008年
month int/str 1-12 表示取值范圍為1-12月
day int/str 1-31 表示取值范圍為1-31日
week int/str 1-53 格里歷2006年12月31日可以寫成2006年-W52-7 擴(kuò)展形式或2006W527 緊湊形式
day_of_week int/str 0-6 或 mon,tue,wed,thu,fri,sat,sun 表示一周中的第幾天响禽,既可以用0-6表示也可以用其英語縮寫表示
hour int/str 0-23 表示取值范圍為0-23時(shí)
minute int/str 0-59 表示取值范圍為0-59分
second int/str 0-59 表示取值范圍為0-59秒
start_date datetime/str XXXX-XX-XX hh:mm:ss 表示開始時(shí)間
end_date datetime/str XXXX-XX-XX hh:mm:ss 表示結(jié)束時(shí)間
timezone datetime.tzinfo/str time zone to use for the date/time calculations 表示時(shí)區(qū)取值

其中,int/str 表示參數(shù)既可以是int類型荚醒,也可以是str類型芋类;datetime/str表示參數(shù)既可以是datetime類型,也可以是str類型

例子:

#表示2017年3月22日17時(shí)19分07秒執(zhí)行該程序
sched.add_job(my_job, 'cron', year=2017,month = 03,day = 22,hour = 17,minute = 19,second = 07)

#表示任務(wù)在6,7,8,11,12月份的第三個(gè)星期五的00:00,01:00,02:00,03:00 執(zhí)行該程序
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秒執(zhí)行該程序一次界阁,相當(dāng)于interval 間隔調(diào)度中seconds = 5
sched.add_job(my_job, 'cron',second = '*/5') 作者:燕洼仙草 https://www.bilibili.com/read/cv7868920/ 出處:bilibili

APScheduler + MySQL

不過我們肯定并不滿足于實(shí)現(xiàn)一個(gè)小小的demo侯繁。

如果我們想要連接MySQL實(shí)現(xiàn)持久化存儲(chǔ)應(yīng)該怎么做呢?

這里需要配置調(diào)度器:

scheduler = BackgroundScheduler({
    'apscheduler.jobstores.default': {
        'type': 'sqlalchemy',
        'url': 'mysql+pymysql://username:password@127.0.0.1:3306/dbname?charset=utf8',
        'tablename': 'api_job'
    },
    'apscheduler.executors.default': {
        'class': 'apscheduler.executors.pool:ThreadPoolExecutor',
        'max_workers': '20'
    },
    'apscheduler.executors.processpool': {
        'type': 'processpool',
        'max_workers': '10'
    },
    'apscheduler.job_defaults.coalesce': 'false',
    'apscheduler.job_defaults.max_instances': '10',
    'apscheduler.timezone': 'UTC',
})

其中泡躯,apscheduler.jobstores.default字段表示存儲(chǔ)器的配置贮竟,字段說明如下:

  • type表示數(shù)據(jù)庫的類型,MySQL屬于SQLAlchemy较剃,因此這里值填寫sqlalchemy
  • url表示存儲(chǔ)器訪問呢的地址咕别,其中的這些字段需要配置:
    • username為你的數(shù)據(jù)庫的用戶名
    • password為對(duì)應(yīng)的賬號(hào)的密碼
    • dbname為數(shù)據(jù)庫名稱
  • tablename表示將定時(shí)任務(wù)數(shù)據(jù)存儲(chǔ)的表名

然后就可以使用配置好的scheduler添加任務(wù)了:

scheduler.add_job(tok, 'interval', seconds=3, id=job_id, coalesce=True, replace_existing=True)

其中id表示任務(wù)的唯一標(biāo)識(shí)符,coalesce表示忽略服務(wù)器宕機(jī)時(shí)間段內(nèi)的任務(wù)執(zhí)行(否則就會(huì)出現(xiàn)服務(wù)器恢復(fù)之后一下子執(zhí)行多次任務(wù)的情況)写穴,replace_existing表示如果有重名的任務(wù)惰拱,直接覆蓋

添加任務(wù)后就可以看到數(shù)據(jù)庫多出了內(nèi)容:


添加任務(wù)后的數(shù)據(jù)庫

這里使用了中文字符串作為id,可以語義地表示任務(wù)

然鵝啊送,要想任務(wù)存儲(chǔ)其他信息怎么辦偿短,這里思來想去欣孤,決定在數(shù)據(jù)庫創(chuàng)建一個(gè)新的表,用于記錄任務(wù)的詳細(xì)信息翔冀,方便后續(xù)查看导街,每次添加任務(wù)時(shí)往該表插值即可,刪除任務(wù)時(shí)也刪除對(duì)應(yīng)的數(shù)據(jù)纤子,由此實(shí)現(xiàn)任務(wù)數(shù)據(jù)的同步搬瑰。

不過需要注意的是,在添加重復(fù)名稱的定時(shí)任務(wù)時(shí)控硼,設(shè)置replace_existing=True泽论,直接覆蓋已有的任務(wù);相應(yīng)地卡乾,在對(duì)其任務(wù)信息表翼悴,我們采用REPLACE替代INSERT語句來執(zhí)行插入操作,其使用方法和INSERT完全一樣幔妨,但如果表中有重復(fù)的數(shù)據(jù)鹦赎,則會(huì)直接覆蓋,其優(yōu)勢(shì)不言而喻误堡。由此古话,實(shí)現(xiàn)了協(xié)同操作。

其數(shù)字孿生任務(wù)信息表的字段可為:


定時(shí)任務(wù)詳情表
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末锁施,一起剝皮案震驚了整個(gè)濱河市陪踩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌悉抵,老刑警劉巖肩狂,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異姥饰,居然都是意外死亡傻谁,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門列粪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來栅螟,“玉大人,你說我怎么就攤上這事篱竭×ν迹” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵掺逼,是天一觀的道長(zhǎng)吃媒。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么赘那? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任刑桑,我火速辦了婚禮,結(jié)果婚禮上募舟,老公的妹妹穿的比我還像新娘祠斧。我一直安慰自己,他們只是感情好拱礁,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布琢锋。 她就那樣靜靜地躺著,像睡著了一般呢灶。 火紅的嫁衣襯著肌膚如雪吴超。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天鸯乃,我揣著相機(jī)與錄音鲸阻,去河邊找鬼。 笑死缨睡,一個(gè)胖子當(dāng)著我的面吹牛鸟悴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播奖年,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼细诸,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了拾并?” 一聲冷哼從身側(cè)響起揍堰,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤鹏浅,失蹤者是張志新(化名)和其女友劉穎嗅义,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體隐砸,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡之碗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了季希。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片褪那。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖式塌,靈堂內(nèi)的尸體忽然破棺而出博敬,到底是詐尸還是另有隱情,我是刑警寧澤峰尝,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布偏窝,位于F島的核電站看幼,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏募判。R本人自食惡果不足惜姆泻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望硼补。 院中可真熱鬧驮肉,春花似錦、人聲如沸已骇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽疾捍。三九已至奈辰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間乱豆,已是汗流浹背奖恰。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留宛裕,地道東北人瑟啃。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像揩尸,于是被迫代替她去往敵國和親蛹屿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容