基本概念
APScheduler有四種組件:
- triggers (觸發器)
- job stores (作業儲存器)
- executors (執行器)
- schedulers (調度器)
觸發器包含調度邏輯。每個作業都有自己的觸發器,該觸發器確定下一步應在何時運行該作業。除了其初始配置之外,觸發器完全是無狀態的。
作業儲存器存放調度的作業。默認的作業存儲器只是將作業保存的內存中,而其他作業則將他們存儲在各種數據庫中。作業的數據在保存到持久性作業存儲中時會序列化,在從作業中加載回去時會反序列化。作業存儲器(默認存儲器除外)不會將作業數據保留在內存中,而是充當在後臺保存,加載,更新和搜索作業的中間人。調度器之間絕對不能共享作業存儲器。
執行器負責處理運行的作業。他們通常通過將作業中的指定可調用對象提交給線程或進程池來執行此操作。作業完成後,執行器通知調度器,發出響應事件。
調度器將其餘部分綁定到一起。通常,您的應用程序中僅運行一個調度器。程序開發人員通常不直接處理作業存儲器,執行器或觸發器。而是調度器提供適當的接口來處理所有這些接口。配置作業存儲器和執行器是通過調度器完成的,添加,修改和刪除作業也是如此。
選擇正確的調度器,作業存儲器,執行器和觸發器
調度器的選擇主要取決於您的編成環境以及您將使用APScheduler做什麼。
以下是選擇調度器的快速指南:
- BlockingScheduler: 當調度器是您的程序中唯一運行的東西時使用。
- BackgroundScheduler: 當您不使用以下任何框架,並希望調度器在應用程序的後臺運行時使用。
- AsyncIOScheduler: 如果您的程序使用asyncio模塊
- GeventScheduler: 如果你的程序使用gevent
- TornadoScheduler: 如果你正在構建Tornado程序
- TwistedScheduler: 如果你正在構建Twisted程序
- QtScheduler:如果你正在構建Qt程序
要選擇合適的作業存儲器,您需要確定是否需要作業持久化。如果你總是在程序開始時重新創建作業,則可以使用默認設置(MemoryJobStore)。但是,如果你需要作業在調度器重新啓動或應用程序崩潰後繼續存在,那麼你的選擇通常可以歸結爲編程環境中使用的工具。但是,如果你可以自由選擇,則建議使用PostgreSQL後端上的SQLAlchemyJobStore,因爲它具有強大的數據完整性保護功能。
同樣的,如果使用了上述框架之一,通常會爲你選擇執行器。默認的ThreadPoolExecutor應該足以滿足大多數用途。如果你的工作量涉及CPU密集型操作,則應考慮改用ProcessPoolExecutor來利用多個CPU內核。你甚至可以同時使用兩者,將進程池執行程序添加爲輔助執行程序。
安排作業時,需要爲其選擇一個觸發器。觸發器確定運行作業時通過其計算日期/時間的邏輯。
APScheduler有三種內置觸發器類型:
- data: 當你想在某個時間點僅運行一次作業時使用
- interval: 當你要以固定的時間間隔運行作業時使用
- cron: 當你要在一天的特定時間定期運行作業時使用
也可以將多個觸發器組合爲一個觸發器,該觸發器可以在所有參與觸發器約定的時間觸發,也可以在任何觸發器觸發時觸發。可見觸發器文檔。
配置調度器
APScheduler提供了很多不同的方式來配置調度器。你可以使用配置字典,也可以將選項作爲關鍵字參數傳遞。你可以先實例化調度器,然後添加作業後配置調度器。這樣,你可以在任何環境下獲得最大的靈活性。
假設要使用默認的作業存儲器和執行器運行BackgroundScheduler:
from apscheduler.schedulers.background import BackgroundScheduler
scheduler = BackgroundScheduler()
代碼實例化一個BackgroundScheduler,它的MemoryJobStore爲“default”,ThreadPoolExecutor爲“default”,默認最大線程數爲10。
現在假設你想要更多,想使用兩個執行器創建兩個作業存儲器,還希望調整新作業的默認值並設置不同的時區。可以嘗試下面的例子:
Method1:
from pytz import utc
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.jobstores.mongodb import MongoDBJobStore
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor
jobstores = {
'mongo': MongoDBJobStore(),
'default': SQLAlchemyJobStore(url='sqlite:///jobs.sqlite')
}
executors = {
'default': ThreadPoolExecutor(20),
'processpool': ProcessPoolExecutor(5)
}
job_defaults = {
'coalesce': False,
'max_instances': 3
}
scheduler = BackgroundScheduler(jobstores=jobstores, executors=executors, job_defaults=job_defaults, timezone=utc)
Method2:
from apscheduler.schedulers.background import BackgroundScheduler
# The "apscheduler." prefix is hard coded
scheduler = BackgroundScheduler({
'apscheduler.jobstores.mongo': {
'type': 'mongodb'
},
'apscheduler.jobstores.default': {
'type': 'sqlalchemy',
'url': 'sqlite:///jobs.sqlite'
},
'apscheduler.executors.default': {
'class': 'apscheduler.executors.pool:ThreadPoolExecutor',
'max_workers': '20'
},
'apscheduler.executors.processpool': {
'type': 'processpool',
'max_workers': '5'
},
'apscheduler.job_defaults.coalesce': 'false',
'apscheduler.job_defaults.max_instances': '3',
'apscheduler.timezone': 'UTC',
})
Method3:
from pytz import utc
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.executors.pool import ProcessPoolExecutor
jobstores = {
'mongo': {'type': 'mongodb'},
'default': SQLAlchemyJobStore(url='sqlite:///jobs.sqlite')
}
executors = {
'default': {'type': 'threadpool', 'max_workers': 20},
'processpool': ProcessPoolExecutor(max_workers=5)
}
job_defaults = {
'coalesce': False,
'max_instances': 3
}
scheduler = BackgroundScheduler()
# .. do something else here, maybe add jobs etc.
scheduler.configure(jobstores=jobstores, executors=executors, job_defaults=job_defaults, timezone=utc)
啓動調度器
調度器調用start()即可啓動調度器。對於BlockingScheduler以外的其他調度器,此調用將立即返回,你可以繼續程序的初始化過程,向調度器添加作業。
對於BlockingScheduler,你只需要在完成所有初始化步驟後調用start()。
調度器啓動後,將無法再更改其設置。
添加作業
有兩種方式向調度器添加作業:
- 通過調用add_job()
- 通過使用scheduler_job()裝飾器
常用第一種方法,第二種方法主要便於聲明再程序運行期間不會更改的作業。add_job()方法返回apscheduler.job.Job實例,你可以再以後使用該實例來修改或刪除作業。
你可以隨時在調度器上調度作業。如果當在添加作業時調度器尚未運行,則將暫停調度作業,並且僅在調度器啓動時才計算其首次運行時間。
重要的是要注意,如果使用執行器或作業存儲器序列化作業,將對作業添加一系列要求:
- List item