提到定時任務調度的時候,相信很多人會想到芹菜celery,要么就寫個腳本塞到crontab中。不過,一個小的定時腳本,要用celery的話太“重”了。所以,我找到了一個輕量級的定時任務調度的庫:schedule。
schedule庫是一個輕量級的定時任務方案,優勢是使用簡單,也不需要做什么配置;缺點是無法動態添加任務,也無法將任務持久化。
庫的安裝還是最簡單的pip install schedule,使用起來也是很容易理解的。我們從最簡單的栗子看起:
import schedule import time def job(): print("I'm working...") schedule.every(10).minutes.do(job) schedule.every().hour.do(job) schedule.every().day.at("10:30").do(job) schedule.every(5).to(10).days.do(job) schedule.every().monday.do(job) schedule.every().wednesday.at("13:15").do(job) while True: schedule.run_pending() time.sleep(1)
這是在pypi上面給出的示例。這個栗子簡單到我不需要怎么解釋。而且,通過這個栗子,我們也可以知道,schedule其實就只是個定時器。在while True死循環中,schedule.run_pending()是保持schedule一直運行,去查詢上面那一堆的任務,在任務中,就可以設置不同的時間去運行。跟crontab是類似的。
但是,如果是多個任務運行的話,實際上它們是按照順序從上往下挨個執行的。如果上面的任務比較復雜,會影響到下面任務的運行時間。比如我們這樣:
import datetime import schedule import time def job1(): print("I'm working for job1") time.sleep(2) print("job1:", datetime.datetime.now()) def job2(): print("I'm working for job2") time.sleep(2) print("job2:", datetime.datetime.now()) def run(): schedule.every(10).seconds.do(job1) schedule.every(10).seconds.do(job2) while True: schedule.run_pending() time.sleep(1)
接下來你就會發現,兩個定時任務並不是10秒運行一次,而是12秒。是的。由於job1和job2本身的執行時間,導致任務延遲了。
其實解決方法也很簡單:用多線程/多進程。
不要幼稚地問我“python中的多線程不是沒有用嗎?”這是兩碼事。開了一條線程,就把job獨立出去運行了,不會占主進程的cpu時間,schedule並沒有花掉執行一個任務的時間,它的開銷只是開啟一條線程的時間,所以,下一次執行就變成了10秒后而不是12秒后。
import datetime import schedule import threading import time def job1(): print("I'm working for job1") time.sleep(2) print("job1:", datetime.datetime.now()) def job2(): print("I'm working for job2") time.sleep(2) print("job2:", datetime.datetime.now()) def job1_task(): threading.Thread(target=job1).start() def job2_task(): threading.Thread(target=job2).start() def run(): schedule.every(10).seconds.do(job1_task) schedule.every(10).seconds.do(job2_task) while True: schedule.run_pending() time.sleep(1)
就是這么簡單。
唯一要注意的是,這里面job不應當是死循環類型的,也就是說,這個線程應該有一個執行完畢的出口。一是因為線程萬一僵死,會是非常棘手的問題;二是下一次定時任務還會開啟一個新的線程,執行次數多了就會演變成災難。如果schedule的時間間隔設置得比job執行的時間短,一樣會線程堆積形成災難,所以,還是需要注意一下的。
schedule這個庫使用起來比較簡單,內容不是很多。我這里介紹的大概用法基本上夠用了,還想了解其他特性的話,可以參考官網:
https://schedule.readthedocs.io/en/stable/