在我們的日常工作自動(dòng)化測(cè)試當(dāng)中,幾乎超過(guò)一半的功能都需要利用定時(shí)的任務(wù)來(lái)推動(dòng)觸發(fā),例如在我們項(xiàng)目中有一個(gè)定時(shí)監(jiān)控模塊,根據(jù)自己設(shè)置的頻率定時(shí)跑測(cè)試用例,定時(shí)檢測(cè)是否存在線(xiàn)上緊急任務(wù)等等,這些都涉及到了有關(guān)定時(shí)任務(wù)的問(wèn)題,很多情況下,大多數(shù)人會(huì)選擇window的任務(wù)計(jì)劃程序,但如果程序不在window平臺(tái)下運(yùn)行,就不能定時(shí)啟動(dòng)了;當(dāng)然也可利用time模塊的time.sleep()方法使程序休眠來(lái)達(dá)到定時(shí)任務(wù)的目的,但定時(shí)任務(wù)多了,代碼可能看起來(lái)不太那么友好且有很大的局限性,因此,此時(shí)的 Apscheduler 框架是你的不二選擇。
Apscheduler
Apscheduler基于Quartz的一個(gè)python定時(shí)任務(wù)框架,實(shí)現(xiàn)Quart的所有功能,相關(guān)的接口調(diào)用起來(lái)比較方便,目前其提供了基于日期、固定時(shí)間間隔以及corntab類(lèi)型的任務(wù),并且同時(shí)可進(jìn)行持久化任務(wù);同時(shí)它提供了多種不同的調(diào)用器,方便開(kāi)發(fā)者根據(jù)自己的需求進(jìn)行使用,也方便與數(shù)據(jù)庫(kù)等第三方的外部持久化儲(chǔ)存機(jī)制進(jìn)行協(xié)同工作,非常強(qiáng)大。
基本原理
總的來(lái)說(shuō),主要是利用python threading Event和Lock鎖來(lái)寫(xiě)的。scheduler在主循環(huán)(main_loop)中, 反復(fù)檢查是否有需要執(zhí)行的任務(wù),完成任務(wù)的檢查函數(shù)為 _process_jobs,主要有那個(gè)幾個(gè)步驟:
1、 詢(xún)問(wèn)儲(chǔ)存的每個(gè)
jobStore
,是否有到期要執(zhí)行的任務(wù)。
2、
due_jobs
不為空,則計(jì)算這些jobs中每個(gè)job需要運(yùn)行的時(shí)間點(diǎn),時(shí)間一到就提交給submit作任務(wù)調(diào)度。
3、在主循環(huán)中,如果不間斷地調(diào)用,而實(shí)際上沒(méi)有要執(zhí)行的job,這會(huì)造成資源浪費(fèi)。因此在程序中,如果每次掉用
_process_jobs
后,進(jìn)行了預(yù)先判斷,判斷下一次要執(zhí)行的job(離現(xiàn)在最近的)還要多長(zhǎng)時(shí)間,作為返回值告訴main_loop, 這時(shí)主循環(huán)就可以去睡一覺(jué),等大約這么長(zhǎng)時(shí)間后再喚醒,執(zhí)行下一次
_process_jobs
。
安裝
1?可以直接使用pip進(jìn)行安裝
2?源碼安裝
### 基礎(chǔ)概念
在A(yíng)pscheduler中主要有以下幾個(gè)非常重要的概念,主要如下:
觸發(fā)器(trigger):
某一個(gè)工作到來(lái)時(shí)引發(fā)的事件,包含調(diào)度的邏輯,每一個(gè)作業(yè)都有它自己的觸發(fā)器,用于決定哪個(gè)作業(yè)任務(wù)會(huì)執(zhí)行,除了它們初始化配置之外,其完全是無(wú)狀態(tài)的。總的來(lái)說(shuō)就是 一個(gè)任務(wù)應(yīng)該在什么時(shí)候執(zhí)行
執(zhí)行器(executor):
主要是處理作業(yè)的運(yùn)行,它將要執(zhí)行的作業(yè)放在新的線(xiàn)程或者線(xiàn)程池中運(yùn)行。執(zhí)行完畢之后,再通知調(diào)度器。基于線(xiàn)程池的操作,可以針對(duì)不同類(lèi)型的作業(yè)任務(wù),更為高效的使用CPU的計(jì)算資源。
作業(yè)存儲(chǔ)(job stores)
保存要調(diào)度的任務(wù),其中除了默認(rèn)的作業(yè)存儲(chǔ)是把作業(yè)保存在內(nèi)存中,其他的作業(yè)存儲(chǔ)是將作業(yè)保存在數(shù)據(jù)庫(kù)中。一個(gè)作業(yè)的數(shù)據(jù)將在保存在持久化的作業(yè)存儲(chǔ)之前,會(huì)對(duì)作業(yè)執(zhí)行序列化操作,當(dāng)重新讀取作業(yè)時(shí),再執(zhí)行反序列化操作。同時(shí),調(diào)度器不能分享同一個(gè)作業(yè)存儲(chǔ)。作業(yè)存儲(chǔ)支持主流的存儲(chǔ)機(jī)制:如redis,mongodb,關(guān)系型數(shù)據(jù)庫(kù),內(nèi)存等等。
調(diào)度器(scheduler):
負(fù)責(zé)將上面幾個(gè)組件聯(lián)系在一起,一般在應(yīng)用中只有一個(gè)調(diào)度器,程序開(kāi)發(fā)者不會(huì)直接操作觸發(fā)器、作業(yè)存儲(chǔ)或執(zhí)行器,而是利用調(diào)度器提供了處理這些合適的接口,作業(yè)存儲(chǔ)和執(zhí)行器的配置都是通過(guò)在調(diào)度器中完成的。
在我們的使用過(guò)程中,選擇合適的 調(diào)度器 是根據(jù)我們的開(kāi)發(fā)環(huán)境以及實(shí)際應(yīng)用來(lái)決定的,根據(jù)IO模型的不同,主要有下面一些常見(jiàn)的調(diào)度器:
- BlockingScheduler:適合于只在進(jìn)程中運(yùn)行單個(gè)任務(wù)的情況
- BackgroundScheduler: 適合于不運(yùn)行使用其他框架時(shí),并希望在程序后臺(tái)執(zhí)行的情況
- AsyncIOScheduler:適合于使用asyncio框架的情況
- GeventScheduler: 適合于使用gevent框架的情況
- TornadoScheduler: 適合于使用Tornado框架的應(yīng)用
- TwistedScheduler: 適合使用Twisted框架的應(yīng)用
- QtScheduler: 適合使用QT的情況
而對(duì)于 作業(yè)存儲(chǔ) ,如果是非持久性作業(yè),使用默認(rèn)的 MemoryStore 就行了,若是持久性任務(wù),那么就需要根據(jù)應(yīng)用環(huán)境來(lái)進(jìn)行選擇。
大多數(shù)情況下, 執(zhí)行器 選擇 ThreadPoolExecutor 就夠用了,但如果涉及到比較消耗CPU的作業(yè),就可以選擇ProcessPoolExecutor* ,以充分利用多核CPU。當(dāng)然也可以同時(shí)配置使用兩個(gè)執(zhí)行器,將進(jìn)程池 ProcessPoolExecutor 調(diào)度器作為你的第二個(gè)執(zhí)行器。
配置調(diào)度器
Apscheduler框架提供了許多調(diào)度器的配置方法,既可以使用配置字典,也可以直接傳遞配置參數(shù)給調(diào)度器使用; 同時(shí)支持先初始化調(diào)度器,添加完作業(yè)任務(wù)后,再來(lái)配置調(diào)度器等。
說(shuō)了這么多,我們可以來(lái)先舉個(gè)簡(jiǎn)單的例子:
上面的代碼生成一個(gè)默認(rèn)的調(diào)度器,默認(rèn)使用名為 default 的 MemoryJobStore,以及使用默認(rèn)名為 default 的 ThreadPoolExecutor ,最大線(xiàn)程數(shù)為10 。
下面進(jìn)行一個(gè)復(fù)雜的配置,同時(shí)使用兩個(gè)作業(yè)存儲(chǔ)和兩個(gè)執(zhí)行器,在這個(gè)配置中,修改默認(rèn)的配置參數(shù),jobstored指的是job持久化,默認(rèn)job運(yùn)行在內(nèi)存中,可持久化在數(shù)據(jù)庫(kù),指定為mongo的MongoDBJobStore或者是使用sqlite的SQLAlchemyJobStore,同時(shí)可指定多種jobstore。
coalesce
:當(dāng)由于某種原因?qū)е履硞€(gè)job積攢了好幾次沒(méi)有實(shí)際運(yùn)行(比如說(shuō)系統(tǒng)掛了5分鐘后恢復(fù),有一個(gè)任務(wù)是每分鐘跑一次的,按道理說(shuō)這5分鐘內(nèi)本來(lái)是“計(jì)劃”運(yùn)行5次的,但實(shí)際沒(méi)有執(zhí)行),如果coalesce為T(mén)rue,下次這個(gè)job被submit給executor時(shí),只會(huì)執(zhí)行1次,也就是最后這次,如果為False,那么會(huì)執(zhí)行5次(不一定,因?yàn)檫€有其他條件,看后面misfiregracetime的解釋?zhuān)?
max_instance
:每個(gè)job在同一時(shí)刻能夠運(yùn)行的最大實(shí)例數(shù),默認(rèn)情況下為1個(gè),可以指定為更大值,這樣即使上個(gè)job還沒(méi)運(yùn)行完同一個(gè)job又被調(diào)度的話(huà)也能夠再開(kāi)一個(gè)線(xiàn)程執(zhí)行。
misfire_grace_time
:?jiǎn)挝粸槊?假設(shè)有這么一種情況,當(dāng)某一job被調(diào)度時(shí)剛好線(xiàn)程池都被占滿(mǎn),調(diào)度器會(huì)選擇將該job排隊(duì)不運(yùn)行,misfiregracetime參數(shù)則是在線(xiàn)程池有可用線(xiàn)程時(shí)會(huì)比對(duì)該job的應(yīng)調(diào)度時(shí)間跟當(dāng)前時(shí)間的差值,如果差值
啟動(dòng)/關(guān)閉調(diào)度器
使用
start()
方法來(lái)啟動(dòng)調(diào)度器,其中須注意的是
BlockingScheduler
需要在初始化之后才能執(zhí)行
start()
,對(duì)于其他的調(diào)度器,調(diào)用
start()
方法都會(huì)直接返回,然后可以繼續(xù)執(zhí)行后面的初始化操作。同時(shí),調(diào)度器啟動(dòng)之后,就不能再更改它的配置了。
在默認(rèn)情況下,調(diào)度器會(huì)等所有的作業(yè)任務(wù)完成后,自動(dòng)關(guān)閉所有的調(diào)度器及作業(yè)存儲(chǔ)。若在使用過(guò)程中不想等待,可以將
wait
參數(shù)選項(xiàng)設(shè)為
False
,則表示直接關(guān)閉:
調(diào)度器監(jiān)聽(tīng)事件
可以給調(diào)度器添加事件監(jiān)聽(tīng)器,調(diào)度器事件只有在某些情況下才會(huì)被觸發(fā),并且可以攜帶某些有用的信息。通過(guò)給
add_listener()
傳遞合適的
mask
參數(shù),可以只監(jiān)聽(tīng)?zhēng)追N特定的事件類(lèi)型,具體類(lèi)型可看源碼中的
event.exception
或者
event.code
值來(lái)做識(shí)別判斷。
作業(yè)及作業(yè)存儲(chǔ)
jobstore提供給scheduler一個(gè)序列化jobs的統(tǒng)一抽象,提供對(duì)scheduler中job的增刪改查接口,根據(jù)存儲(chǔ)backend的不同,分以下幾種:
MemoryJobStore
:沒(méi)有序列化,jobs就存在內(nèi)存里,增刪改查也都是在內(nèi)存中操作
SQLAlchemyJobStore
:所有sqlalchemy支持的數(shù)據(jù)庫(kù)都可以做為backend,增刪改查操作轉(zhuǎn)化為對(duì)應(yīng)backend的sql語(yǔ)句
MongoDBJobStore
:用mongodb作backend
RedisJobStore
: 用redis作backend
Job是框架承接目前需要執(zhí)行的工作和任務(wù),我們可以在系統(tǒng)運(yùn)行過(guò)程中進(jìn)行動(dòng)態(tài)的增加、修改、刪除、查詢(xún)等操作。
1、添加作業(yè)
上面是通過(guò)
add_job()
來(lái)添加作業(yè),另外還有一種方式是通過(guò)修飾器
scheduled_job
來(lái)動(dòng)態(tài)裝飾 Job 的實(shí)際函數(shù)
2、移除作業(yè)
3、暫停作業(yè)
4、恢復(fù)作業(yè)
5、修改作業(yè)
6、獲取Job列表
獲得調(diào)度作業(yè)的列表,可以使用
get_jobs()
來(lái)完成,它會(huì)返回所有的job實(shí)例,同時(shí)也可使用
print_jobs()
來(lái)輸出所有格式化的作業(yè)列表。也可以利用
get_job(任務(wù)ID)
獲取指定任務(wù)的作業(yè)列表
作業(yè)運(yùn)行控制
add_job()
方法的第二個(gè)參數(shù)是trigger,它管理著作業(yè)任務(wù)的調(diào)度方式,它可以被設(shè)置為
data
、
interval
、
corn
三種類(lèi)別。對(duì)于不同的設(shè)置類(lèi)別,對(duì)應(yīng)的參數(shù)也有所不同,具體如下:
1、corn 定時(shí)調(diào)度,即規(guī)定在某一時(shí)刻執(zhí)行
使用例子:
2、interval間隔調(diào)度,即每隔多久執(zhí)行一次
3、data定時(shí)調(diào)度,即設(shè)置后作業(yè)只會(huì)執(zhí)行一次,是最基本的調(diào)度模式
總結(jié)
Apscheduler是一個(gè)非常強(qiáng)大且易用的類(lèi)庫(kù),可以方便我們快速的搭建一些強(qiáng)大的定時(shí)任務(wù)或者定時(shí)監(jiān)控類(lèi)的調(diào)度系統(tǒng),在實(shí)際工作中非常有用,同時(shí)其也提供了不少的擴(kuò)展點(diǎn)。
以上所述是小編給大家介紹的Python 定時(shí)框架 Apscheduler,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺(jué)得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
