Python3-可用來定時任務的四種實現(xiàn)方式

最近做一個小程序開發(fā)任務,主要負責后臺部分開發(fā)别厘;根據(jù)項目需求虱饿,需要實現(xiàn)三個定時任務:

定時更新微信token,需要2小時更新一次丹允;
商品定時上線郭厌;
定時檢測后臺服務是否存活;

有興趣者可加QQ:3271330538

可點擊666白嫖領取

使用Python去實現(xiàn)這三個任務雕蔽,這里需要使用定時相關知識點折柠;
Python實現(xiàn)定點與定時任務方式比較多,找到下面四中實現(xiàn)方式批狐,每個方式都有自己應用場景扇售;下面來快速介紹Python中常用的定時任務實現(xiàn)方式:

1.循環(huán)+sleep;

2.線程模塊中Timer類嚣艇;

3.schedule模塊承冰;

4.定時框架:APScheduler

在開始之前先設定一個任務(這樣不用依賴外部環(huán)境):

1:定時或者定點監(jiān)測CPU與內存使用率;

2:將時間食零,CPU困乒,內存使用情況保存到日志文件;

先來實現(xiàn)系統(tǒng)監(jiān)測功能:
準備工作:安裝psutil:pip install psutil
功能實現(xiàn)

psutil:獲取系統(tǒng)信息模塊贰谣,可以獲取CPU娜搂,內存,磁盤等的使用情況

import psutil
import time
import datetime

logfile:監(jiān)測信息寫入文件

def MonitorSystem(logfile = None):

獲取cpu使用情況

cpuper = psutil.cpu_percent()

獲取內存使用情況:系統(tǒng)內存大小吱抚,使用內存百宇,有效內存,內存使用率

mem = psutil.virtual_memory()

內存使用率

memper = mem.percent

獲取當前時間

now = datetime.datetime.now()
ts = now.strftime('%Y-%m-%d %H:%M:%S')
line = f'{ts} cpu:{cpuper}%, mem:{memper}%'
print(line)
if logfile:
logfile.write(line)
12345678910111213141516171819
代碼運行結果:

2019-03-21 14:23:41 cpu:0.6%, mem:77.2%
1
接下來我們要實現(xiàn)定時監(jiān)測秘豹,比如3s監(jiān)測一下系統(tǒng)資源使用情況携御。

最簡單使用方式:sleep

這種方式最簡單,直接使用while+sleep就可以實現(xiàn):

def loopMonitor():
while True:
MonitorSystem()

2s檢查一次

time.sleep(3)
loopMonitor()
123456
輸出結果:

2019-03-21 14:28:42 cpu:1.5%, mem:77.6%
2019-03-21 14:28:45 cpu:1.6%, mem:77.6%
2019-03-21 14:28:48 cpu:1.4%, mem:77.6%
2019-03-21 14:28:51 cpu:1.4%, mem:77.6%
2019-03-21 14:28:54 cpu:1.3%, mem:77.6%
12345
這種方式存在問題:只能處理單個定時任務。

又來了新任務:需要每秒監(jiān)測網(wǎng)絡收發(fā)字節(jié)啄刹,代碼實現(xiàn)如下:

def MonitorNetWork(logfile = None):

獲取網(wǎng)絡收信息

netinfo = psutil.net_io_counters()

獲取當前時間

now = datetime.datetime.now()
ts = now.strftime('%Y-%m-%d %H:%M:%S')
line = f'{ts} bytessent={netinfo.bytes_sent}, bytesrecv={netinfo.bytes_recv}'
print(line)
if logfile:
logfile.write(line)
MonitorNetWork()
1234567891011
代碼執(zhí)行結果:

2019-03-21 14:47:21 bytessent=169752183, bytesrecv=1107900973
1
如果我們同時在while循環(huán)中監(jiān)測兩個任務會有等待問題涮坐,不能每秒監(jiān)測網(wǎng)絡情況。

Timer實現(xiàn)方式

timer最基本理解就是定時器誓军,我們可以啟動多個定時任務膊升,這些定時器任務是異步執(zhí)行,所以不存在等待順序執(zhí)行問題谭企。

先來看Timer的基本使用:

導入:from threading import Timer

主要方法:

Timer方法說明Timer(interval, function, args=None, kwargs=None)創(chuàng)建定時器cancel()取消定時器start()使用線程方式執(zhí)行join(self, timeout=None)等待線程執(zhí)行結束

定時器只能執(zhí)行一次廓译,如果需要重復執(zhí)行,需要重新添加任務债查;

我們先來看基本使用:

from threading import Timer

記錄當前時間

print(datetime.datetime.now())

3S執(zhí)行一次

sTimer = Timer(3, MonitorSystem)

1S執(zhí)行一次

nTimer = Timer(1, MonitorNetWork)

使用線程方式執(zhí)行

sTimer.start()
nTimer.start()

等待結束

sTimer.join()
nTimer.join()

記錄結束時間

print(datetime.datetime.now())
123456789101112131415
輸出結果:

2019-03-21 15:13:36.739798
2019-03-21 15:13:37 bytessent=171337324, bytesrecv=1109002349
2019-03-21 15:13:39 cpu:1.4%, mem:93.2%
2019-03-21 15:13:39.745187
1234
可以看到非区,花費時間為3S,但是我們想要做的是每秒監(jiān)控網(wǎng)絡狀態(tài)盹廷;如何處理征绸。

Timer只能執(zhí)行一次,所以執(zhí)行完成之后需要再次添加任務俄占,我們對代碼進行修改:

from threading import Timer
import psutil
import time
import datetime
def MonitorSystem(logfile = None):
cpuper = psutil.cpu_percent()
mem = psutil.virtual_memory()
memper = mem.percent
now = datetime.datetime.now()
ts = now.strftime('%Y-%m-%d %H:%M:%S')
line = f'{ts} cpu:{cpuper}%, mem:{memper}%'
print(line)
if logfile:
logfile.write(line)

啟動定時器任務管怠,每三秒執(zhí)行一次

Timer(3, MonitorSystem).start()
def MonitorNetWork(logfile = None):
netinfo = psutil.net_io_counters()
now = datetime.datetime.now()
ts = now.strftime('%Y-%m-%d %H:%M:%S')
line = f'{ts} bytessent={netinfo.bytes_sent}, bytesrecv={netinfo.bytes_recv}'
print(line)
if logfile:
logfile.write(line)

啟動定時器任務,每秒執(zhí)行一次

Timer(1, MonitorNetWork).start()
MonitorSystem()
MonitorNetWork()
12345678910111213141516171819202122232425262728
執(zhí)行結果:

2019-03-21 15:18:21 cpu:1.5%, mem:93.2%
2019-03-21 15:18:21 bytessent=171376522, bytesrecv=1109124678
2019-03-21 15:18:22 bytessent=171382215, bytesrecv=1109128294
2019-03-21 15:18:23 bytessent=171384278, bytesrecv=1109129702
2019-03-21 15:18:24 cpu:1.9%, mem:93.2%
2019-03-21 15:18:24 bytessent=171386341, bytesrecv=1109131110
2019-03-21 15:18:25 bytessent=171388527, bytesrecv=1109132600
2019-03-21 15:18:26 bytessent=171390590, bytesrecv=1109134008
12345678
從時間中可以看到缸榄,這兩個任務可以同時進行不存在等待問題渤弛。

Timer的實質是使用線程方式去執(zhí)行任務,每次執(zhí)行完后會銷毀甚带,所以不必擔心資源問題她肯。

調度模塊:schedule

schedule是一個第三方輕量級的任務調度模塊,可以按照秒鹰贵,分晴氨,小時,日期或者自定義事件執(zhí)行時間碉输;

安裝方式:

pip install schedule

我們來看一個例子:

import datetime
import schedule
import time
def func():
now = datetime.datetime.now()
ts = now.strftime('%Y-%m-%d %H:%M:%S')
print('do func time :',ts)
def func2():
now = datetime.datetime.now()
ts = now.strftime('%Y-%m-%d %H:%M:%S')
print('do func2 time:',ts)
def tasklist():

清空任務

schedule.clear()

創(chuàng)建一個按秒間隔執(zhí)行任務

schedule.every(1).seconds.do(func)

創(chuàng)建一個按2秒間隔執(zhí)行任務

schedule.every(2).seconds.do(func2)

執(zhí)行10S

for i in range(10):
schedule.run_pending()
time.sleep(1)
tasklist()
1234567891011121314151617181920212223
執(zhí)行結果:

do func time : 2019-03-22 08:51:38
do func2 time: 2019-03-22 08:51:39
do func time : 2019-03-22 08:51:39
do func time : 2019-03-22 08:51:40
do func2 time: 2019-03-22 08:51:41
do func time : 2019-03-22 08:51:41
do func time : 2019-03-22 08:51:42
do func2 time: 2019-03-22 08:51:43
do func time : 2019-03-22 08:51:43
do func time : 2019-03-22 08:51:44
do func2 time: 2019-03-22 08:51:45
do func time : 2019-03-22 08:51:45
do func time : 2019-03-22 08:51:46
12345678910111213
執(zhí)行過程分析:

1>因為在jupyter下執(zhí)行籽前,所以先將schedule任務清空;
2>按時間間在schedule中隔添加任務敷钾;
3>這里按照秒間隔添加func枝哄,按照兩秒間隔添加func2;
4>schedule添加任務后,需要查詢任務并執(zhí)行任務闰非;
5>為了防止占用資源膘格,每秒查詢到點任務峭范,然后順序執(zhí)行财松;

第5個順序執(zhí)行怎么理解,我們修改func函數(shù),里面添加time.sleep(2)

然后只執(zhí)行func工作辆毡,輸出結果:

do func time : 2019-03-22 09:00:59
do func time : 2019-03-22 09:01:02
do func time : 2019-03-22 09:01:05
123
可以看到時間間隔為3S菜秦,為什么不是1S?

因為這個按照順序執(zhí)行舶掖,func休眠2S球昨,循環(huán)任務查詢休眠1S,所以會存在這個問題眨攘。

在我們使用這種方式執(zhí)行任務需要注意這種阻塞現(xiàn)象主慰。

我們看下schedule模塊常用使用方法:

schedule.every(1)創(chuàng)建Job, seconds.do(func)按秒間隔查詢并執(zhí)行

schedule.every(1).seconds.do(func)

添加任務按分執(zhí)行

schedule.every(1).minutes.do(func)

添加任務按天執(zhí)行

schedule.every(1).days.do(func)

添加任務按周執(zhí)行

schedule.every().weeks.do(func)

添加任務每周1執(zhí)行,執(zhí)行時間為下周一這一時刻時間

schedule.every().monday.do(func)

每周1鲫售,1點15開始執(zhí)行

schedule.every().monday.at("12:00").do(job)
123456789101112
這種方式局限性:如果工作任務回非常耗時就會影響其他任務執(zhí)行共螺。我們可以考慮使用并發(fā)機制配置這個模塊使用。

任務框架APScheduler

APScheduler是Python的一個定時任務框架情竹,用于執(zhí)行周期或者定時任務藐不,

可以基于日期、時間間隔秦效,及類似于Linux上的定時任務crontab類型的定時任務雏蛮;

該該框架不僅可以添加、刪除定時任務阱州,還可以將任務存儲到數(shù)據(jù)庫中挑秉,實現(xiàn)任務的持久化,使用起來非常方便苔货。

安裝方式:pip install apscheduler

apscheduler組件及簡單說明:

1>triggers(觸發(fā)器):觸發(fā)器包含調度邏輯衷模,每一個作業(yè)有它自己的觸發(fā)器
2>job stores(作業(yè)存儲):用來存儲被調度的作業(yè),默認的作業(yè)存儲器是簡單地把作業(yè)任務保存在內存中,支持存儲到MongoDB蒲赂,Redis數(shù)據(jù)庫中
3> executors(執(zhí)行器):執(zhí)行器用來執(zhí)行定時任務阱冶,只是將需要執(zhí)行的任務放在新的線程或者線程池中運行
4>schedulers(調度器):調度器是將其它部分聯(lián)系在一起,對使用者提供接口,進行任務添加滥嘴,設置木蹬,刪除。我們的Python學習扣qun:784若皱,758镊叁,214,看看前輩們是如何學習的走触!交流經驗晦譬!
來看一個簡單例子:

import time
from apscheduler.schedulers.blocking import BlockingScheduler
def func():
now = datetime.datetime.now()
ts = now.strftime('%Y-%m-%d %H:%M:%S')
print('do func time :',ts)
def func2():

耗時2S

now = datetime.datetime.now()
ts = now.strftime('%Y-%m-%d %H:%M:%S')
print('do func2 time:',ts)
time.sleep(2)
def dojob():

創(chuàng)建調度器:BlockingScheduler

scheduler = BlockingScheduler()

添加任務,時間間隔2S

scheduler.add_job(func, 'interval', seconds=2, id='test_job1')

添加任務,時間間隔5S

scheduler.add_job(func2, 'interval', seconds=3, id='test_job2')
scheduler.start()
dojob()
123456789101112131415161718192021
輸出結果:

do func time : 2019-03-22 10:32:20
do func2 time: 2019-03-22 10:32:21
do func time : 2019-03-22 10:32:22
do func time : 2019-03-22 10:32:24
do func2 time: 2019-03-22 10:32:24
do func time : 2019-03-22 10:32:26
123456
輸出結果中可以看到:任務就算是有延時,也不會影響其他任務執(zhí)行互广。

APScheduler框架提供豐富接口去實現(xiàn)定時任務敛腌,可以去參考官方文檔去查看使用方式卧土。

最后選擇:

簡單總結上面四種定時定點任務實現(xiàn):

1:循環(huán)+sleep方式適合簡答測試,

2:timer可以實現(xiàn)定時任務像樊,但是對定點任務來說尤莺,需要檢查當前時間點;

3:schedule可以定點定時執(zhí)行生棍,但是需要在循環(huán)中檢測任務颤霎,而且存在阻塞;

4:APScheduler框架更加強大涂滴,可以直接在里面添加定點與定時任務友酱;

綜合考慮,決定使用APScheduler框架柔纵,實現(xiàn)簡單粹污,只需要直接創(chuàng)建任務,并將添加到調度器中即可首量。

有興趣者交流可加QQ:3271330538 可點擊666白嫖領取

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末壮吩,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子加缘,更是在濱河造成了極大的恐慌鸭叙,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拣宏,死亡現(xiàn)場離奇詭異沈贝,居然都是意外死亡,警方通過查閱死者的電腦和手機勋乾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進店門宋下,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人辑莫,你說我怎么就攤上這事学歧。” “怎么了各吨?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵枝笨,是天一觀的道長。 經常有香客問我揭蜒,道長横浑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任屉更,我火速辦了婚禮徙融,結果婚禮上,老公的妹妹穿的比我還像新娘瑰谜。我一直安慰自己欺冀,他們只是感情好树绩,可當我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著脚猾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪砚哗。 梳的紋絲不亂的頭發(fā)上龙助,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天,我揣著相機與錄音蛛芥,去河邊找鬼提鸟。 笑死,一個胖子當著我的面吹牛仅淑,可吹牛的內容都是我干的称勋。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼涯竟,長吁一口氣:“原來是場噩夢啊……” “哼赡鲜!你這毒婦竟也來了?” 一聲冷哼從身側響起庐船,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤银酬,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后筐钟,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體揩瞪,經...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年篓冲,在試婚紗的時候發(fā)現(xiàn)自己被綠了李破。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡壹将,死狀恐怖嗤攻,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情诽俯,我是刑警寧澤屯曹,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站惊畏,受9級特大地震影響恶耽,放射性物質發(fā)生泄漏。R本人自食惡果不足惜颜启,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一偷俭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缰盏,春花似錦涌萤、人聲如沸淹遵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽透揣。三九已至,卻和暖如春川抡,著一層夾襖步出監(jiān)牢的瞬間辐真,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工崖堤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留侍咱,地道東北人。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓密幔,卻偏偏與公主長得像楔脯,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子胯甩,可洞房花燭夜當晚...
    茶點故事閱讀 45,870評論 2 361

推薦閱讀更多精彩內容