<h1>APScheduler定時任務(wù)</h1><p>上次測試女神聽了我的建議,已經(jīng)做好了要給項目添加定時任務(wù)的決定了。但是之前提供的四種方式中,她不知道具體選擇哪一個。為了和女神更近一步,我把我入行近10年收藏的干貨免費拿出來分享給女神,希望女神凌晨2點再找我的時候,不再是因為要給他調(diào)程序了。</p><p>Python中定時任務(wù)的解決方案,總體來說有四種,分別是:crontab、 scheduler、 Celery、 APScheduler,其中 crontab不適合多臺服務(wù)器的配置、scheduler太過于簡單、 Celery依賴的軟件比較多,比較耗資源。最好的解決方案就是 APScheduler。</p><p>APScheduler使用起來十分方便。提供了基于日期、固定時間間隔以及 crontab類型的任務(wù)。還可以在程序運行過程中動態(tài)的新增任務(wù)和刪除任務(wù)。在任務(wù)運行過程中,還可以把任務(wù)存儲起來,下次啟動運行依然保留之前的狀態(tài)。另外最重要的一個特點是,因為他是基于 Python語言的庫,所以是可以跨平臺的,一段代碼,處處運行!</p><p>在這里我來給大家詳細介紹一下具體的用法。</p><h2>一、安裝:</h2><p>安裝非常簡單,通過 pip install apscheduler即可。</p><h2>二、基本使用:</h2><p>先來看一段代碼,然后再來給大家詳細講解其中的細節(jié):</p><ol><li><p><img src="https://upload-images.jianshu.io/upload_images/6620012-1e0fa8a3ec47c84b.png" class="uploaded-img" width="auto" height="auto">
</p></li></ol><p>其中 BlockingScheduler是阻塞性的調(diào)度器,是最基本的調(diào)度器,下面調(diào)用 start方法就會阻塞當(dāng)前進程,所以如果你的程序除了調(diào)度進程沒有其他后臺進程,那么是可以是否的,否則這個調(diào)度器會阻塞你程序的正常執(zhí)行。</p><p>接下來就是定義一個 my_clock函數(shù),這個函數(shù)就是需要定時調(diào)度的任務(wù)代碼。</p><p>然后就是實例化一個 BlockingScheduler對象,并把 my_clock添加到任務(wù)調(diào)度中。然后看 interval參數(shù),這里用的是間隔的方式來調(diào)度,調(diào)度頻率是 seconds=3,也就是每3秒執(zhí)行一次。</p><p>執(zhí)行結(jié)果如下:<img src="https://upload-images.jianshu.io/upload_images/6620012-219c233a62973760.jpeg" class="uploaded-img" width="auto" height="auto"></p><p>可以看到每隔3秒鐘的時間會執(zhí)行一次。說明定時任務(wù)已經(jīng)成功執(zhí)行了!</p><p>在了解了 APScheduler的基本使用后,再來對 APScheduler的四個基本對象做個了解,這樣才能從全局掌握 APScheduler。</p><h2>三、四個基本對象:</h2><h3>1. 觸發(fā)器(triggers):</h3><p>觸發(fā)器就是根據(jù)你指定的觸發(fā)方式,比如是按照時間間隔,還是按照 crontab觸發(fā),觸發(fā)條件是什么等。每個任務(wù)都有自己的觸發(fā)器。</p><h3>2. 任務(wù)存儲器(job stores):</h3><p>任務(wù)存儲器是可以存儲任務(wù)的地方,默認情況下任務(wù)保存在內(nèi)存,也可將任務(wù)保存在各種數(shù)據(jù)庫中。任務(wù)存儲進去后,會進行序列化,然后也可以反序列化提取出來,繼續(xù)執(zhí)行。</p><h3>3. 執(zhí)行器(executors):</h3><p>執(zhí)行器的目的是安排任務(wù)到線程池或者進程池中運行的。</p><h3>4. 調(diào)度器(schedulers):</h3><p>任務(wù)調(diào)度器是屬于整個調(diào)度的總指揮官。他會合理安排作業(yè)存儲器、執(zhí)行器、觸發(fā)器進行工作,并進行添加和刪除任務(wù)等。調(diào)度器通常是只有一個的。開發(fā)人員很少直接操作觸發(fā)器、存儲器、執(zhí)行器等。因為這些都由調(diào)度器自動來實現(xiàn)了。</p><p><img src="https://upload-images.jianshu.io/upload_images/6620012-d7462dd83dc8a2ee.jpeg" class="uploaded-img" width="auto" height="auto"></p><h2>四、觸發(fā)器:</h2><p>觸發(fā)器有兩種,第一種是 interval,第二種是 crontab。interval可以具體指定多少時間間隔執(zhí)行一次。crontab可以指定執(zhí)行的日期策略。以下分別進行講解。</p><h3>1.?date觸發(fā)器:</h3><p>在某個日期時間只觸發(fā)一次事件。示例代碼如下:</p><ol><li><p><img src="https://upload-images.jianshu.io/upload_images/6620012-80b31cb26acd3ef7.png" class="uploaded-img" width="auto" height="auto">
</p></li></ol><p>更多請參考:https://apscheduler.readthedocs.io/en/stable/modules/triggers/date.html</p><h3>2.?interval觸發(fā)器:</h3><p>想要在固定的時間間隔觸發(fā)事件。interval的觸發(fā)器可以設(shè)置以下的觸發(fā)參數(shù):</p><ol><li><p>weeks:周。整形。</p></li><li><p>days:一個月中的第幾天。整形。</p></li><li><p>hours:小時。整形。</p></li><li><p>minutes:分鐘。整形。</p></li><li><p>seconds:秒。整形。</p></li><li><p>start_date:間隔觸發(fā)的起始時間。</p></li><li><p>end_date:間隔觸發(fā)的結(jié)束時間。</p></li><li><p>jitter:觸發(fā)的時間誤差。</p></li></ol><ol><li><p><img src="https://upload-images.jianshu.io/upload_images/6620012-ffa0348917bdfa7b.png" class="uploaded-img" width="auto" height="auto">
</p></li></ol><p>在每天的11點24分觸發(fā)事件。更多請參考:https://apscheduler.readthedocs.io/en/stable/modules/triggers/interval.html</p><h3>3.?crontab觸發(fā)器:</h3><p>在某個確切的時間周期性的觸發(fā)事件??梢允褂玫膮?shù)如下:</p><ol><li><p>year:4位數(shù)字的年份。</p></li><li><p>month:1-12月份。</p></li><li><p>day:1-31日。</p></li><li><p>week:1-53周。</p></li><li><p>day_of_week:一個禮拜中的第幾天(?0-6或者?mon、?tue、?wed、?thu、?fri、?sat、?sun)。</p></li><li><p>hour:?0-23小時。</p></li><li><p>minute:?0-59分鐘。</p></li><li><p>second:?0-59秒。</p></li><li><p>start_date:?datetime類型或者字符串類型,起始時間。</p></li><li><p>end_date:?datetime類型或者字符串類型,結(jié)束時間。</p></li><li><p>timezone:時區(qū)。</p></li><li><p>jitter:任務(wù)觸發(fā)的誤差時間。</p></li></ol><p>也可以用表達式類型,可以用以下方式:</p><p><img src="https://upload-images.jianshu.io/upload_images/6620012-6e55bcdb764984f5.png" class="uploaded-img" width="auto" height="auto">
</p><p>示例如下:</p><ol><li><p><img src="https://upload-images.jianshu.io/upload_images/6620012-45883e58e1b4cabe.png" class="uploaded-img" width="auto" height="auto">
</p></li></ol><h2>五、調(diào)度器:</h2><ol><li><p>BlockingScheduler:適用于調(diào)度程序是進程中唯一運行的進程,調(diào)用?start函數(shù)會阻塞當(dāng)前線程,不能立即返回。</p></li><li><p>BackgroundScheduler:適用于調(diào)度程序在應(yīng)用程序的后臺運行,調(diào)用?start后主線程不會阻塞。</p></li><li><p>AsyncIOScheduler:適用于使用了?asyncio模塊的應(yīng)用程序。</p></li><li><p>GeventScheduler:適用于使用?gevent模塊的應(yīng)用程序。</p></li><li><p>TwistedScheduler:適用于構(gòu)建?Twisted的應(yīng)用程序。</p></li><li><p>QtScheduler:適用于構(gòu)建?Qt的應(yīng)用程序。</p></li></ol><h2>六、任務(wù)存儲器:</h2><p>任務(wù)存儲器的選擇有兩種。一是內(nèi)存,也是默認的配置。二是數(shù)據(jù)庫。使用內(nèi)存的方式是簡單高效,但是不好的是,一旦程序出現(xiàn)問題,重新運行的話,會把之前已經(jīng)執(zhí)行了的任務(wù)重新執(zhí)行一遍。數(shù)據(jù)庫則可以在程序崩潰后,重新運行可以從之前中斷的地方恢復(fù)正常運行。有以下幾種選擇:</p><ol><li><p>MemoryJobStore:沒有序列化,任務(wù)存儲在內(nèi)存中,增刪改查都是在內(nèi)存中完成。</p></li><li><p>SQLAlchemyJobStore:使用?SQLAlchemy這個?ORM框架作為存儲方式。</p></li><li><p>MongoDBJobStore:使用?mongodb作為存儲器。</p></li><li><p>RedisJobStore:使用?redis作為存儲器。</p></li></ol><h2>七、執(zhí)行器:</h2><p>執(zhí)行器的選擇取決于應(yīng)用場景。通常默認的 ThreadPoolExecutor已經(jīng)在大部分情況下是可以滿足我們需求的。如果我們的任務(wù)涉及到一些 CPU密集計算的操作。那么應(yīng)該考慮 ProcessPoolExecutor。然后針對每種程序, apscheduler也設(shè)置了不同的 executor:</p><ol><li><p>ThreadPoolExecutor:線程池執(zhí)行器。</p></li><li><p>ProcessPoolExecutor:進程池執(zhí)行器。</p></li><li><p>GeventExecutor:?Gevent程序執(zhí)行器。</p></li><li><p>TornadoExecutor:?Tornado程序執(zhí)行器。</p></li><li><p>TwistedExecutor:?Twisted程序執(zhí)行器。</p></li><li><p>AsyncIOExecutor:?asyncio程序執(zhí)行器。</p></li></ol><h2>八、定時任務(wù)調(diào)度配置:</h2><p>這里我們用一個例子來說明。比如我想這樣配置</p><ol><li><p>執(zhí)行器:</p></li><ul><li><p>配置?default執(zhí)行器為?ThreadPoolExecutor,并且設(shè)置最多的線程數(shù)是20個。</p></li><li><p><</p></li></ul><li><p>存儲器:</p></li><ul><li><p>配置?default的任務(wù)存儲器為?SQLAlchemyJobStore(使用SQLite)。</p></li><li><p><</p></li></ul><li><p>任務(wù)配置:</p></li><li><p>設(shè)置?coalesce為?False:設(shè)置這個目的是,比如由于某個原因?qū)е履硞€任務(wù)積攢了很多次沒有執(zhí)行(比如有一個任務(wù)是1分鐘跑一次,但是系統(tǒng)原因斷了5分鐘),如果?coalesce=True,那么下次恢復(fù)運行的時候,會只執(zhí)行一次,而如果設(shè)置?coalesce=False,那么就不會合并,會5次全部執(zhí)行。</p></li><li><p>max_instances=5:同一個任務(wù)同一時間最多只能有5個實例在運行。比如一個耗時10分鐘的job,被指定每分鐘運行1次,如果我?max_instance值5,那么在第6~10分鐘上,新的運行實例不會被執(zhí)行,因為已經(jīng)有5個實例在跑了。</p></li></ol><p>那么代碼如下:</p><ol><li><p><img src="https://upload-images.jianshu.io/upload_images/6620012-e6d38e76ad9fbb9e.png" class="uploaded-img" width="auto" height="auto"><img src="https://upload-images.jianshu.io/upload_images/6620012-834ebd16476ff0c7.png" class="uploaded-img" width="auto" height="auto"><img src="https://upload-images.jianshu.io/upload_images/6620012-2514436bb55ba32b.png" class="uploaded-img" width="auto" height="auto">
</p></li><li><p><span style="color: rgba(0, 0, 0, 0.85); font-size: x-large;">九、任務(wù)操作:</span></p></li></ol><h3>1. 添加任務(wù):</h3><p>使用 scheduler.add_job(job_obj,args,id,trigger,trigger_kwargs)。</p><h3>2. 刪除任務(wù):</h3><p>使用 scheduler.remove_job(job_id,jobstore=None)。</p><h3>3. 暫停任務(wù):</h3><p>使用 scheduler.pause_job(job_id,jobstore=None)。</p><h3>4. 恢復(fù)任務(wù):</h3><p>使用 scheduler.resume_job(job_id,jobstore=None)。</p><h3>5. 修改某個任務(wù)屬性信息:</h3><p>使用 scheduler.modify_job(job_id,jobstore=None,changes)。</p><h3>6. 修改單個作業(yè)的觸發(fā)器并更新下次運行時間:</h3><p>使用 scheduler.reschedule_job(job_id,jobstore=None,trigger=None,**trigger_args)</p><h3>7. 輸出作業(yè)信息:</h3><p>使用 scheduler.print_jobs(jobstore=None,out=sys.stdout)</p><h2>十、異常監(jiān)聽:</h2><p>當(dāng)我們的任務(wù)拋出異常后,我們可以監(jiān)聽到,然后把錯誤信息進行記錄。示例代碼如下:</p><ol><li><p>from apscheduler.schedulers.blocking import BlockingScheduler</p></li><li><p>from apscheduler.events import EVENT_JOB_EXECUTED, EVENT_JOB_ERROR</p></li><li><p>import datetime</p></li><li><p>import logging</p></li><li><p>
</p></li><li><p># 配置日志顯示</p></li><li><p><img src="https://upload-images.jianshu.io/upload_images/6620012-9595d5363d1baf09.png" class="uploaded-img" width="auto" height="auto"><img src="https://upload-images.jianshu.io/upload_images/6620012-9ac054139f51377a.png" class="uploaded-img" width="auto" height="auto"><img src="https://upload-images.jianshu.io/upload_images/6620012-aa37af931f761ee0.png" class="uploaded-img" width="auto" height="auto">
</p></li></ol><p>以上便是 APScheduler庫的詳細用法了。如果我們需要在項目中開一個定時功能,完全可以選擇 APScheduler,輕量又功能強大。</p><p>這次女神再也不用2點跑到公司去加班啦~</p><p><img src="https://upload-images.jianshu.io/upload_images/6620012-5e2e6e8c43b1338a.png" class="uploaded-img" width="auto" height="auto">
</p>
python定時任務(wù)最強框架APScheduler詳細教程
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。