最近學習到了 python 中兩種開啓定時任務的方法,和你們分享一下心得。html
- sched.scheduler()
- threading.Timer()
sched 定時任務
使用sched的套路以下:python
s = sched.scheduler(time.time, time.sleep)
s.enter(delay, priority, func1, (arg1, arg2, ...))
s.enter(delay, priority, func2, (arg1, arg2, arg3, ...))
s.run()
第一步新建一個調度器;markdown
第二步添加任務,能夠添加多個任務;多線程
第三步讓調度器開始運行。函數
第二步各參數含義:oop
- delay 相對於調度器添加這個任務時刻的延時,以秒爲單位;
- priority 優先級,數字越小優先級越高;
- func1 任務函數
- (arg1, arg2, ...) 任務函數的參數
import time import sched # 第一個工做函數 # 第二個參數 @starttime 表示任務開始的時間 # 很明顯參數在創建這個任務的時候就已經傳遞過去了,至於任務什麼時候開始執行就由調度器決定了 def worker(msg, starttime): print u"任務執行的時刻", time.time(), "傳達的消息是", msg, '任務創建時刻', starttime # 建立一個調度器示例 # 第一參數是獲取時間的函數,第二個參數是延時函數 print('---------- 兩個簡單的例子 -------------') print('程序啓動時刻:', time.time()) s = sched.scheduler(time.time, time.sleep) s.enter(1, 1, worker, ('hello', time.time())) s.enter(3, 1, worker, ('world', time.time())) s.run() # 這一個 s.run() 啓動上面的兩個任務 print('睡眠2秒前時刻:', time.time()) time.sleep(2) print('睡眠2秒結束時刻:', time.time()) # 重點關注下面2個任務,創建時間,啓動時間 # 2個任務的創建時間都很好計算,但有沒有發現 "hello world [3]" 的啓動時間比創建時間晚 13 秒, # 這不就是2個 sleep 的總延時嗎?因此說啓動時間並不必定就是 delay 能指定的,還須要看具體的程序環境, # 若是程序堵塞的很厲害,已經浪費了一大段的時間尚未到 scheduler 能調度這個任務,當 scheduler 能調度這個 # 任務的時候,發現 delay 已通過去了, scheduler 爲了彌補「罪過」,會立刻啓動這個任務。 # 任務 "hello world [15]" 就是一個很好的例子,正常狀況下,程序沒有阻塞的那麼厲害,在scheduler 能調度這個任務的時候 # 發現 delay 還沒到就等待,若是 delay 時間到了就能夠在剛好指定的延時調用這個任務。 print('\n\n---------- 兩個複雜的例子 -------------') s.enter(3, 1, worker, ('hello world [3]', time.time())) print('睡眠7秒前時刻:', time.time()) time.sleep(7) print('睡眠7秒結束時刻:', time.time()) s.enter(15, 1, worker, ('hello world [15]', time.time())) print('睡眠6秒前時刻:', time.time()) time.sleep(6) print('睡眠6秒結束時刻:', time.time()) s.run() # 過了2秒以後,啓動另一個任務 print('程序結束時刻', time.time())
---------- 兩個簡單的例子 ------------- 程序啓動時刻: 1481731389.4 任務執行的時刻 1481731390.4 傳達的消息是 hello 任務創建時刻 1481731389.4 任務執行的時刻 1481731392.41 傳達的消息是 world 任務創建時刻 1481731389.4 睡眠2秒前時刻: 1481731392.41 睡眠2秒結束時刻: 1481731394.41 ---------- 兩個複雜的例子 ------------- 睡眠7秒前時刻: 1481731394.41 睡眠7秒結束時刻: 1481731401.42 睡眠6秒前時刻: 1481731401.42 睡眠6秒結束時刻: 1481731407.42 任務執行的時刻 1481731407.42 傳達的消息是 hello world [3] 任務創建時刻 1481731394.41 任務執行的時刻 1481731416.43 傳達的消息是 hello world [15] 任務創建時刻 1481731401.42 程序結束時刻 1481731416.43
自調任務1
任務快結束時利用 scheduler 又從新調用本身讓本身「活過來」。post
# 計數器,一個循環任務,總共讓本身執行3次 total = 0 # 第二個工做函數,自調任務,本身開啓定時並啓動。 def worker2(msg, starttime): global total total += 1 print('當前時刻:', time.time(), '消息是:', msg, ' 啓動時間是:', starttime) # 只要沒有讓本身調用到第3次,那麼繼續重頭開始執行本任務 if total < 3: # 這裏的delay 能夠從新指定 s.enter(5, 2, worker2, ('perfect world %d' % (total), time.time())) s.run() print('程序開始時刻:', time.time()) # 開啓自調任務 s.enter(5, 2, worker2, ('perfect world %d' % (total), time.time())) s.run() print('程序結束時刻:', time.time())
程序開始時刻: 1481731439.42 當前時刻: 1481731444.43 消息是: perfect world 0 啓動時間是: 1481731439.42 當前時刻: 1481731449.44 消息是: perfect world 1 啓動時間是: 1481731444.43 當前時刻: 1481731454.44 消息是: perfect world 2 啓動時間是: 1481731449.44 程序結束時刻: 1481731454.44
Threading.Timer() 定時任務
from threading import Timer import time def func(msg, starttime): print('程序啓動時刻:', starttime, '當前時刻:', time.time(), '消息內容 --> %s' % (msg)) # 下面的兩個語句和上面的 scheduler 效果同樣的 Timer(5, func, ('hello', time.time())).start() Timer(3, func, ('world', time.time())).start()
程序啓動時刻: 1481731467.28 當前時刻: 1481731470.28 消息內容 --> world
程序啓動時刻: 1481731467.28 當前時刻: 1481731472.28 消息內容 --> hello
循環任務2
利用 threading.Timer() 創建的自調任務學習
count = 0 def loopfunc(msg,starttime): global count print('啓動時刻:', starttime, ' 當前時刻:', time.time(), '消息 --> %s' % (msg)) count += 1 if count < 3: Timer(3, loopfunc, ('world %d' % (count), time.time())).start() Timer(3, loopfunc, ('world %d' % (count), time.time())).start()
啓動時刻: 1481731476.35 當前時刻: 1481731479.35 消息 --> world 0 啓動時刻: 1481731479.35 當前時刻: 1481731482.35 消息 --> world 1 啓動時刻: 1481731482.35 當前時刻: 1481731485.35 消息 --> world 2
自用,測試,待完善......
方法一(推薦使用)
from threading import Timer import time def interval_time(timeStr): #timeStr = '2018-5-3 09:48:15' 時間格式 #調用格式 interval_time('2018-5-3 09:48:05') timeArray = time.strptime(timeStr, "%Y-%m-%d %H:%M:%S") timestamp = time.mktime(timeArray) return int(timestamp-time.time()) def func(msg, starttime): print('程序啓動時刻:', starttime, '當前時刻:', time.time(), '消息內容 --> %s' % (msg)) # 下面的兩個語句和上面的 scheduler 效果同樣的 Timer(interval_time('2018-5-3 09:48:05'), func, ('hello', time.time())).start() Timer(interval_time('2018-5-3 09:48:15'), func, ('world', time.time())).start()
方法二(使用sched)測試