如何用 Python 實現(xiàn)優(yōu)先級調(diào)度器?

作者:kingname
來源:未聞Code
Python 自帶一個調(diào)度器模塊sched,它能為你實現(xiàn)優(yōu)先級隊列/延遲隊列和定時隊列。
這個模塊的使用非常簡單,首先以延遲隊列為例:
import sched
def do_work(name):
print(f'你好:{name}')
sch = sched.scheduler()
sch.enter(5, 1, do_work, argument=('kingname', ))
sch.run()
代碼運行以后,會卡在sch.run()這里,5秒鐘以后執(zhí)行do_work('kingname'),運行效果如下圖所示:

其中,sch.enter()的第一個參數(shù)為延遲的時間,單位為秒,第二個參數(shù)為優(yōu)先級,數(shù)字越小優(yōu)先級越高。當兩個任務(wù)同時要執(zhí)行時,優(yōu)先級高的先執(zhí)行。但需要注意的是,如果你這樣寫:
import sched
def do_work(name):
print(f'你好:{name}')
sch = sched.scheduler()
sch.enter(5, 2, do_work, argument=('產(chǎn)品經(jīng)理', ))
sch.enter(5, 1, do_work, argument=('kingname', ))
sch.run()
那么先打印出來的是你好:產(chǎn)品經(jīng)理,如下圖所示:

為什么這里優(yōu)先級失效了?1的優(yōu)先級大于2,應(yīng)該先運行下面的才對啊。
這是由于,只有當兩個任務(wù)同時運行的時候,才會去檢查優(yōu)先級。如果兩個任務(wù)觸發(fā)的時間一前一后,那么還輪不到比較優(yōu)先級。
由于延遲隊列的延遲是相對于當前運行這一行代碼的時間來計算的,后一行代碼比前一行代碼晚了幾毫秒,所以實際上產(chǎn)品經(jīng)理這一行會先到時間,所以就會先運行。
為了使用絕對的精確時間,我們可以使用另外一個方法:
import sched
import time
import datetime
def do_work(name):
print(f'你好:{name}')
sch = sched.scheduler(time.time, time.sleep)
start_time = datetime.datetime.now() + datetime.timedelta(seconds=10)
start_time_ts = start_time.timestamp()
sch.enterabs(start_time_ts, 2, do_work, argument=('產(chǎn)品經(jīng)理', ))
sch.enterabs(start_time_ts, 1, do_work, argument=('kingname', ))
sch.run()
運行效果如下圖所示:

sch.enterabs()的第一個參數(shù)是任務(wù)開始時間的時間戳,這是一個絕對時間,這個時間可以使用datetime模塊來生成,或者其他你熟悉的方式。后面的參數(shù)和sch.enter()完全一樣。
如果你要運行的函數(shù)帶有多個參數(shù)或者默認參數(shù),那么可以使用下面的方式傳入?yún)?shù):
import sched
import time
import datetime
def do_work(name, place, work='寫代碼'):
print(f'你好:{name},你在:{place}{work}')
sch = sched.scheduler(time.time, time.sleep)
start_time = datetime.datetime.now() + datetime.timedelta(seconds=10)
start_time_ts = start_time.timestamp()
sch.enter(5, 2, do_work, argument=('產(chǎn)品經(jīng)理', '杭州'), kwargs={'work': '寫需求文檔'})
sch.enterabs(start_time_ts, 1, do_work, argument=('kingname', '產(chǎn)品經(jīng)理旁邊'), kwargs={'work': '看著她'})
sch.run()
argument參數(shù)對應(yīng)的元組存放普通參數(shù),kwargs對應(yīng)的字典存放帶參數(shù)名的參數(shù)。

還不過癮?試試它們
▲Python 中如何實現(xiàn)參數(shù)化測試?
▲酷炫!Python函數(shù)耗時異常自動化監(jiān)控!
