Release3.0.5
AlexGrönholm
December21,2015
Contents
1
TableofContents
1.1Userguide.....................1.2Versionhistory...................1.3MigratingfrompreviousversionsofAPScheduler1.4ContributingtoAPScheduler............1.5ExtendingAPScheduler..............Indicesandtables
.......................................................................................................................................
331013151619
2
i
ii
APSchedulerDocumentation,Release3.0.5
AdvancedPythonScheduler(APScheduler)isaPythonlibrarythatletsyouscheduleyourPythoncodetobeexecutedlater,eitherjustonceorperiodically.Youcanaddnewjobsorremoveoldonesontheflyasyouplease.Ifyoustoreyourjobsinadatabase,theywillalsosurviveschedulerrestartsandmaintaintheirstate.Whentheschedulerisrestarted,itwillthenrunallthejobsitshouldhaverunwhileitwasoffline1.
Amongotherthings,APSchedulercanbeusedasacross-platform,applicationspecificreplacementtoplatformspe-cificschedulers,suchasthecrondaemonortheWindowstaskscheduler.Pleasenote,however,thatAPSchedulerisnotadaemonorserviceitself,nordoesitcomewithanycommandlinetools.Itisprimarilymeanttoberuninsideexistingapplications.Thatsaid,APSchedulerdoesprovidesomebuildingblocksforyoutobuildaschedulerserviceortorunadedicatedschedulerprocess.
APSchedulerhasthreebuilt-inschedulingsystemsyoucanuse:
•Cron-stylescheduling(withoptionalstart/endtimes)
•Interval-basedexecution(runsjobsonevenintervals,withoptionalstart/endtimes)•One-offdelayedexecution(runsjobsonce,onasetdate/time)
Youcanmixandmatchschedulingsystemsandthebackendswherethejobsarestoredanywayyoulike.Supportedbackendsforstoringjobsinclude:
•Memory
•SQLAlchemy(anyRDBMSsupportedbySQLAlchemyworks)•MongoDB•Redis
APScheduleralsointegrateswithseveralcommonPythonframeworks,like:
•asyncio(PEP3156)•gevent•Tornado•Twisted
•Qt(usingeitherPyQtorPySide)
1
Thecutoffperiodforthisisalsoconfigurable.
Contents1
APSchedulerDocumentation,Release3.0.5
2Contents
CHAPTER1
TableofContents
1.1Userguide
1.1.1InstallingAPScheduler
Thepreferredinstallationmethodisbyusingpip:
$pipinstallapschedulerIfyoudon’thavepipinstalled,youcaneasilyinstallitbydownloadingandrunningget-pip.py.
If,forsomereason,pipwon’twork,youcanmanuallydownloadtheAPSchedulerdistributionfromPyPI,extractandtheninstallit:
$pythonsetup.pyinstall1.1.2Codeexamples
ThesourcedistributioncontainstheexamplesdirectorywhereyoucanfindmanyworkingexamplesforusingAPSchedulerindifferentways.Theexamplescanalsobebrowsedonline.
1.1.3Basicconcepts
APSchedulerhasfourkindsofcomponents:
•triggers•jobstores•executors•schedulers
Triggerscontaintheschedulinglogic.Eachjobhasitsowntriggerwhichdetermineswhenthejobshouldberunnext.Beyondtheirinitialconfiguration,triggersarecompletelystateless.
Jobstoreshousethescheduledjobs.Thedefaultjobstoresimplykeepsthejobsinmemory,butothersstoretheminvariouskindsofdatabases.Ajob’sdataisserializedwhenitissavedtoapersistentjobstore,anddeserializedwhenit’sloadedbackfromit.Jobstores(otherthanthedefaultone)don’tkeepthejobdatainmemory,butactasmiddlemenforsaving,loading,updatingandsearchingjobsinthebackend.Jobstoresmustneverbesharedbetweenschedulers.
3
APSchedulerDocumentation,Release3.0.5
Executorsarewhathandletherunningofthejobs.Theydothistypicallybysubmittingthedesignatedcallableinajobtoathreadorprocesspool.Whenthejobisdone,theexecutornotifiestheschedulerwhichthememitsanappropriateevent.
Schedulersarewhatbindtheresttogether.Youtypicallyhaveonlyoneschedulerrunninginyourapplication.Theapplicationdeveloperdoesn’tnormallydealwiththejobstores,executorsortriggersdirectly.Instead,theschedulerprovidestheproperinterfacetohandleallthose.Configuringthejobstoresandexecutorsisdonethroughthescheduler,asisadding,modifyingandremovingjobs.
1.1.4Choosingtherightscheduler,jobstoresandexecutors
Yourchoiceofschedulerdependsmostlyonyourprogrammingenvironmentandwhatyou’llbeusingAPSchedulerfor.Here’saquickguideforchoosingascheduler:
•BlockingScheduler:usewhenthescheduleristheonlythingrunninginyourprocess
•BackgroundScheduler:usethenyou’renotusinganyoftheframeworksbelow,andwanttheschedulertoruninthebackgroundinsideyourapplication
•AsyncIOScheduler:useifyourapplicationusestheasynciomodule•GeventScheduler:useifyourapplicationusesgevent
•TornadoScheduler:useifyou’rebuildingaTornadoapplication•TwistedScheduler:useifyou’rebuildingaTwistedapplication•QtScheduler:useifyou’rebuildingaQtapplicationSimpleenough,yes?
Topicktheappropriatejobstore,youneedtodeterminewhetheryouneedjobpersistenceornot.Ifyoualwaysrecreateyourjobsatthestartofyourapplication,thenyoucanprobablygowiththedefault(MemoryJobStore).Butifyouneedyourjobstopersistoverschedulerrestartsorapplicationcrashes,thenyourchoiceusuallyboilsdowntowhattoolsareusedinyourprogrammingenvironment.If,however,youareinthepositiontochoosefreely,thenSQLAlchemyJobStoreonaPostgreSQLbackendistherecommendedchoiceduetoitsstrongdataintegrityprotection.
Likewise,thechoiceofexecutorsisusuallymadeforyouifyouuseoneoftheframeworksabove.Otherwise,thedefaultThreadPoolExecutorshouldbegoodenoughformostpurposes.IfyourworkloadinvolvesCPUintensiveoperations,youshouldconsiderusingProcessPoolExecutorinsteadtomakeuseofmultipleCPUcores.Youcouldevenusebothatonce,addingtheprocesspoolexecutorasasecondaryexecutor.
YoucanfindthepluginnamesofeachjobstoreandexecutortypeintheirrespectiveAPIdocumentationpages.
1.1.5Configuringthescheduler
APSchedulerprovidesmanydifferentwaystoconfigurethescheduler.Youcanuseaconfigurationdictionaryoryoucanpassintheoptionsaskeywordarguments.Youcanalsoinstantiatetheschedulerfirst,addjobsandconfiguretheschedulerafterwards.Thiswayyougetmaximumflexibilityforanyenvironment.
ThefulllistofschedulerlevelconfigurationoptionscanbefoundontheAPIreferenceoftheBaseSchedulerclass.SchedulersubclassesmayalsohaveadditionaloptionswhicharedocumentedontheirrespectiveAPIreferences.ConfigurationoptionsforindividualjobstoresandexecutorscanlikewisebefoundontheirAPIreferencepages.Let’ssayyouwanttorunBackgroundSchedulerinyourapplicationwiththedefaultjobstoreandthedefaultexecutor:
4Chapter1.TableofContents
APSchedulerDocumentation,Release3.0.5
fromapscheduler.schedulers.backgroundimportBackgroundSchedulerscheduler=BackgroundScheduler()#Initializetherestoftheapplicationhere,orbeforetheschedulerinitializationThiswillgetyouaBackgroundSchedulerwithaMemoryJobStorenamed“default”andaThreadPoolExecutornamed“default”withadefaultmaximumthreadcountof10.
Now,supposeyouwantmore.Youwanttohavetwojobstoresusingtwoexecutorsandyoualsowanttotweakthedefaultvaluesfornewjobsandsetadifferenttimezone.Thefollowingthreeexamplesarecompletelyequivalent,andwillgetyou:
•aMongoDBJobStorenamed“mongo”
•anSQLAlchemyJobStorenamed“default”(usingSQLite)•aThreadPoolExecutornamed“default”,withaworkercountof20•aProcessPoolExecutornamed“processpool”,withaworkercountof5•UTCasthescheduler’stimezone
•coalescingturnedofffornewjobsbydefault•adefaultmaximuminstancelimitof3fornewjobsMethod1:
frompytzimportutcfromfromfromfromapscheduler.schedulers.backgroundimportBackgroundSchedulerapscheduler.jobstores.mongodbimportMongoDBJobStoreapscheduler.jobstores.sqlalchemyimportSQLAlchemyJobStoreapscheduler.executors.poolimportThreadPoolExecutor,ProcessPoolExecutorjobstores={'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,Method2:
fromapscheduler.schedulers.backgroundimportBackgroundScheduler#The\"apscheduler.\"prefixishardcodedscheduler=BackgroundScheduler({'apscheduler.jobstores.mongo':{'type':'mongodb'},1.1.Userguide5
APSchedulerDocumentation,Release3.0.5
'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:
frompytzimportutcfromapscheduler.schedulers.backgroundimportBackgroundSchedulerfromapscheduler.jobstores.sqlalchemyimportSQLAlchemyJobStorefromapscheduler.executors.poolimportProcessPoolExecutorjobstores={'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()#..dosomethingelsehere,maybeaddjobsetc.scheduler.configure(jobstores=jobstores,executors=executors,job_defaults=job_defaults,timezone=utc
1.1.6Startingthescheduler
Startingtheschedulerisdonebysimplycallingstart()onthescheduler.Forschedulersotherthan~apsched-uler.schedulers.blocking.BlockingScheduler,thiscallwillreturnimmediatelyandyoucancontinuetheinitializationprocessofyourapplication,possiblyaddingjobstothescheduler.
ForBlockingScheduler,youwillonlywanttocallstart()afteryou’redonewithanyinitializationsteps.Note:Aftertheschedulerhasbeenstarted,youcannolongeralteritssettings.
6Chapter1.TableofContents
APSchedulerDocumentation,Release3.0.5
1.1.7Addingjobs
Therearetwowaystoaddjobstoascheduler:1.bycallingadd_job()
2.bydecoratingafunctionwithscheduled_job()
Thefirstwayisthemostcommonwaytodoit.Thesecondwayismostlyaconveniencetodeclarejobsthatdon’tchangeduringtheapplication’sruntime.Theadd_job()methodreturnsaapscheduler.job.Jobinstancethatyoucanusetomodifyorremovethejoblater.
Youcanschedulejobsonthescheduleratanytime.Iftheschedulerisnotyetrunningwhenthejobisadded,thejobwillbescheduledtentativelyanditsfirstruntimewillonlybecomputedwhentheschedulerstarts.
Itisimportanttonotethatifyouuseanexecutororjobstorethatserializesthejob,itwilladdacouplerequirementsonyourjob:
1.Thetargetcallablemustbegloballyaccessible2.Anyargumentstothecallablemustbeserializable
Ofthebuiltinjobstores,onlyMemoryJobStoredoesn’tserializejobs.Ofthebuiltinexecutors,onlyProcessPoolEx-ecutorwillserializejobs.
Important:Ifyouschedulejobsinapersistentjobstoreduringyourapplication’sinitialization,youMUSTdefineanexplicitIDforthejobandusereplace_existing=Trueoryouwillgetanewcopyofthejobeverytimeyourapplicationrestarts!
Tip:Torunajobimmediately,omittriggerargumentwhenaddingthejob.
1.1.8Removingjobs
Whenyouremoveajobfromthescheduler,itisremovedfromitsassociatedjobstoreandwillnotbeexecutedanymore.Therearetwowaystomakethishappen:
1.bycallingremove_job()withthejob’sIDandjobstorealias2.bycallingremove()ontheJobinstanceyougotfromadd_job()
Thelattermethodisprobablymoreconvenient,butitrequiresthatyoustoresomewheretheJobinstanceyoureceivedwhenaddingthejob.Forjobsscheduledviathescheduled_job(),thefirstwayistheonlyway.Ifthejob’sscheduleends(i.e.itstriggerdoesn’tproduceanyfurtherruntimes),itisautomaticallyremoved.Example:
job=scheduler.add_job(myfunc,'interval',minutes=2)job.remove()Same,usinganexplicitjobID:
scheduler.add_job(myfunc,'interval',minutes=2,id='my_job_id')scheduler.remove_job('my_job_id')1.1.Userguide7
APSchedulerDocumentation,Release3.0.5
1.1.9Pausingandresumingjobs
YoucaneasilypauseandresumejobsthrougheithertheJobinstanceorthescheduleritself.Whenajobispaused,itsnextruntimeisclearedandnofurtherruntimeswillbecalculatedforituntilthejobisresumed.Topauseajob,useeithermethod:
•apscheduler.job.Job.pause()
•apscheduler.schedulers.base.BaseScheduler.pause_job()Toresume:
•apscheduler.job.Job.resume()
•apscheduler.schedulers.base.BaseScheduler.resume_job()
1.1.10Gettingalistofscheduledjobs
Togetamachineprocessablelistofthescheduledjobs,youcanusetheget_jobs()method.ItwillreturnalistofJobinstances.Ifyou’reonlyinterestedinthejobscontainedinaparticularjobstore,thengiveajobstorealiasasthesecondargument.
Asaconvenience,youcanusetheprint_jobs()methodwhichwillprintoutaformattedlistofjobs,theirtriggersandnextruntimes.
1.1.11Modifyingjobs
Youcanmodifyanyjobattributesbycallingeitherapscheduler.job.Job.modify()ormodify_job().YoucanmodifyanyJobattributesexceptforid.Example:
job.modify(max_instances=6,name='Alternatename')Ifyouwanttoreschedulethejob–thatis,changeitsapscheduler.job.Job.reschedule()orreschedule_job().triggerforthejobandrecalculateitsnextruntimebasedonthenewtrigger.Example:
trigger,youcanuseeitherThesemethodsconstructanew
scheduler.reschedule_job('my_job_id',trigger='cron',minute='*/5')1.1.12Shuttingdownthescheduler
Toshutdownthescheduler:
scheduler.shutdown()Bydefault,theschedulershutsdownitsjobstoresandexecutorsandwaitsuntilallcurrentlyexecutingjobsarefinished.Ifyoudon’twanttowait,youcando:
scheduler.shutdown(wait=False)Thiswillstillshutdownthejobstoresandexecutorsbutdoesnotwaitforanyrunningtaskstocomplete.
8Chapter1.TableofContents
APSchedulerDocumentation,Release3.0.5
1.1.13Limitingthenumberofconcurrentlyexecutinginstancesofajob
Bydefault,onlyoneinstanceofeachjobisallowedtoberunatthesametime.Thismeansthatifthejobisabouttoberunbutthepreviousrunhasn’tfinishedyet,thenthelatestrunisconsideredamisfire.Itispossibletosetthemaximumnumberofinstancesforaparticularjobthattheschedulerwillletrunconcurrently,byusingthemax_instanceskeywordargumentwhenaddingthejob.
1.1.14Missedjobexecutionsandcoalescing
Sometimestheschedulermaybeunabletoexecuteascheduledjobatthetimeitwasscheduledtorun.Themostcommoncaseiswhenajobisscheduledinapersistentjobstoreandtheschedulerisshutdownandrestartedafterthejobwassupposedtoexecute.Whenthishappens,thejobisconsideredtohave“misfired”.Theschedulerwillthencheckeachmissedexecutiontimeagainstthejob’smisfire_grace_timeoption(whichcanbesetonper-jobbasisorgloballyinthescheduler)toseeiftheexecutionshouldstillbetriggered.Thiscanleadintothejobbeingexecutedseveraltimesinsuccession.
Ifthisbehaviorisundesirableforyourparticularusecase,itispossibletousecoalescingtorollallthesemissedexecutionsintoone.Inotherwords,ifcoalescingisenabledforthejobandtheschedulerseesoneormorequeuedexecutionsforthejob,itwillonlytriggeritonce.Nomisfireeventswillbesentforthe“bypassed”runs.
1.1.15Schedulerevents
Itispossibletoattacheventlistenerstothescheduler.Schedulereventsarefiredoncertainoccasions,andmaycarryadditionalinformationinthemconcerningthedetailsofthatparticularevent.Itispossibletolistentoonlyparticulartypesofeventsbygivingtheappropriatemaskargumenttoadd_listener(),OR’ingthedifferentconstantstogether.Thelistenercallableiscalledwithoneargument,theeventobject.
Seethedocumentationfortheeventsmoduleforspecificsontheavailableeventsandtheirattributes.Example:
defmy_listener(event):ifevent.exception:print('Thejobcrashed:(')else:print('Thejobworked:)')scheduler.add_listener(my_listener,EVENT_JOB_EXECUTED|EVENT_JOB_ERROR)1.1.16Reportingbugs
Abugtrackerisprovidedbybitbucket.org.
1.1.17Gettinghelp
Ifyouhaveproblemsorotherquestions,youcaneither:
•Askonthe#apschedulerchannelonFreenodeIRC•AskontheAPSchedulerGooglegroup,or
•AskonStackOverflowandtagyourquestionwiththeapschedulertag
1.1.Userguide9
APSchedulerDocumentation,Release3.0.5
1.2Versionhistory
TofindouthowtomigrateyourapplicationfromapreviousversionofAPScheduler,seethemigrationsection.
1.2.13.0.5
•Fixedcrontriggeralwayscoalescingmissedruntimesintoasingleruntime(contributedbymonklof)•Fixedinfiniteloopinthecrontriggerwhenanout-of-boundsvaluewasgiveninanexpression
•FixeddebugloggingdisplayingthenextwakeuptimeintheUTCtimezoneinsteadofthescheduler’sconfiguredtimezone
•AllowedunicodefunctionreferencesinPython2
1.2.23.0.4
•Fixedmemoryleakinthebaseexecutorclass(contributedbyStefanNordhausen)
1.2.33.0.3
•Fixedcompatibilitywithpymongo3.0
1.2.43.0.2
•FixedValueErrorwhenthetargetcallablehasadefaultkeywordargumentthatwasn’toverridden•Fixedwrongjobsortorderinsomejobstores
•Fixedexceptionwhenloadingalljobsfromtheredisjobstorewhentherearepausedjobsinit•FixedAttributeErrorwhenprintingajoblistwhentherewerependingjobs•Addedsetuptoolsasanexplicitrequirementininstallrequirements
1.2.53.0.1
•Awidervarietyoftargetcallablescannowbescheduledsothatthejobsarestillserializable(staticmethodsonPython3.3+,unboundmethodsonallexceptPython3.2)
•Attemptingtoserializeanon-serializableJobnowraisesahelpfulexceptionduringserialization.ThankstoJeremyMorganforpointingthisout.
•FixedtablecreationwithSQLAlchemyJobStoreonMySQL/InnoDB
•Fixedstartdategettingsettoofarinthefuturewithatimezonedifferentfromthelocalone•Fixed_run_job_error()beingcalledwiththeincorrectnumberofargumentsinmostexecutors
10Chapter1.TableofContents
APSchedulerDocumentation,Release3.0.5
1.2.63.0.0
•Addedsupportfortimezones(specialthankstoCurtisVogtforhelpwiththisone)
•SplittheoldSchedulerclassintoBlockingSchedulerandBackgroundSchedulerandaddedintegrationforasyn-cio(PEP3156),Gevent,Tornado,TwistedandQteventloops•Overhauledthejobstoresystemformuchbetterscalability•Addedtheabilitytomodify,reschedule,pauseandresumejobs
•DroppedtheShelvejobstorebecauseitcouldnotworkwiththenewjobstoresystem
•Droppedthemax_runsoptionandruncountingofjobssinceitcouldnotbeimplementedreliably•Addingjobsisnowdoneexclusivelythroughadd_job()–theshortcutstotriggerswereremoved•Addedtheend_dateparametertocronandintervaltriggers
•Itisnowpossibletoaddajobdirectlytoanexecutorwithoutscheduling,byomittingthetriggerargument•Replacedthethreadpoolwithapluggableexecutorsystem
•Addedsupportforrunningjobsinsubprocesses(viatheprocesspoolexecutor)•Switchedfromnosetopy.testforrunningunittests
1.2.72.1.0
•AddedRedisjobstore
•Addeda“standalone”modethatrunstheschedulerinthecallingthread•FixeddisksynchronizationinShelveJobStore•SwitchedtoPyPy1.9forPyPycompatibilitytesting•DroppedPython2.4support
•FixedSQLAlchemy0.8compatibilityinSQLAlchemyJobStore•Variousdocumentationimprovements
1.2.82.0.3
•Theschedulernowclosesthejobstorethatisbeingremoved,andalljobstoresonshutdown()bydefault•AddedthelastexpressioninthedayfieldofCronTrigger(thanksrcaselli)
•RaiseaTypeErrorwhenfieldswithinvalidnamesarepassedtoCronTrigger(thanksChristyO’Reilly)•Fixedthepersistent.pyexamplebyshuttingdownthescheduleronCtrl+C•AddedPyPy1.8andCPython3.3tothetestsuite
•DroppedPyPy1.4-1.5andCPython3.1fromthetestsuite•Updatedsetup.cfgforcompatibilitywithdistutils2/packaging
•Examples,documentationsourcesandunittestsarenowpackagedinthesourcedistribution
1.2.Versionhistory11
APSchedulerDocumentation,Release3.0.5
1.2.92.0.2
•Removedtheuniqueconstraintfromthe“name”columnintheSQLAlchemyjobstore
•FixedoutputfromScheduler.print_jobs()whichdidnotpreviouslyoutputalineendingattheend
1.2.102.0.1
•Fixedcronstylejobsgettingwrongdefaultvalues
1.2.112.0.0
•Addedconfigurablejobstoreswithseveralpersistentback-ends(shelve,SQLAlchemyandMongoDB)•Addedthepossibilitytolistenforjobevents(execution,error,misfire,finish)onascheduler•Addedanoptionalstarttimeforcron-stylejobs
•Addedoptionaljobexecutioncoalescingforsituationswhereseveralexecutionsofthejobaredue•Addedanoptiontolimitthemaximumnumberofconcurrenctlyexecutinginstancesofthejob•Allowedconfigurationofmisfiregracetimesonaper-jobbasis•Allowedjobstobeexplicitlynamed
•Alltriggersnowacceptdatesinstringform(YYYY-mm-ddHH:MM:SS)
•Jobsarenowruninathreadpool;youcaneithersupplyyourownPEP3148compliantthreadpoolorletAPSchedulercreateitsown
•Maximumruncountcanbeconfiguredforalljobs,notjustthoseusinginterval-basedscheduling
•Fixedav1.xdesignflawthatcausedjobstobeexecutedtwicewhentheschedulerthreadwaswokenupwhilestillwithintheallowablerangeoftheirpreviousexecutiontime(issues#5,#7)
•Changeddefaultsforcron-stylejobstobemoreintuitive–itwillnowdefaulttoallminimumvaluesforfieldslowerthantheleastsignificantexplicitlydefinedfield
1.2.121.3.1
•Fixedtimedifferencecalculationtotakeintoaccountshiftstoandfromdaylightsavingtime
1.2.131.3.0
•Added__repr__()implementationstoexpressions,fields,triggers,andjobstohelpwithdebugging•Addedthedump_jobsmethodonScheduler,whichgivesahelpfullistingofalljobsscheduledonit•Fixedpositionalweekday(3thfrietc.)expressionsnotworkingexceptinsomeedgecases(fixes#2)
•RemovedautogeneratedAPIdocumentationformoduleswhicharenotpartofthepublicAPI,asitmightconfusesomeusers
Note:Positionalweekdaysarenowusedwiththedayfield,notweekday.
12Chapter1.TableofContents
APSchedulerDocumentation,Release3.0.5
1.2.141.2.1
•Fixedregression:add_cron_job()inSchedulerwascreatingaCronTriggerwiththewrongparameters(fixes#1,#3)
•Fixed:iftheschedulerisrestarted,clearthe“stopped”flagtoallowjobstobescheduledagain
1.2.151.2.0
•Addedtheweekoptionforcronschedules•Addedthedaemonicconfigurationoption
•Fixedabugincronexpressionliststhatcouldcausevalidfiringtimestobemissed•Fixedunschedulingboundmethodsviaunschedule_func()
•ChangedCronTriggerconstructorargumentnamestomatchthoseinScheduler
1.2.161.01
•Fixedacornercasewherethecombinationofhourandday_of_weekparameterswouldcauseincorrecttimingforacrontrigger
1.3MigratingfrompreviousversionsofAPScheduler
1.3.1Fromv2.xto3.0
The3.0seriesisAPIincompatiblewithpreviousreleasesduetoadesignoverhaul.Schedulerchanges
•Theconceptof“standalonemode”isgone.Forstandalone=True,useBlockingSchedulerinstead,andforstandalone=False,useBackgroundScheduler.BackgroundSchedulermatchestheoldde-faultsemantics.
•Jobdefaults(likemisfire_grace_timeandcoalesce)mustnowbepassedinadictionaryasthejob_defaultsoptiontoconfigure().Whensupplyinganini-styleconfigurationasthefirstargument,theywillneedacorrespondingjob_defaults.prefix.
•Theconfigurationkeyprefixforjobstoreswaschangedfromjobstore.tojobstores.tomatchthedict-styleconfigurationbetter.
•Themax_runsoptionhasbeendroppedsincetheruncountercouldnotbereliablypreservedwhenreplacingajobwithanotheronewiththesameID.Tomakeupforthis,theend_dateoptionwasaddedtocronandintervaltriggers.
•Theoldthreadpoolisgone,replacedbyThreadPoolExecutor.Thismeansthattheoldthreadpooloptionsarenolongervalid.SeeConfiguringthescheduleronhowtoconfigureexecutors.
•Thetrigger-specificschedulingmethodshavebeenremovedentirelyfromthescheduler.Usethegenericadd_job()methodorthescheduled_job()decoratorinstead.Thesignaturesofthesemethodswerechangedsignificantly.
1.3.MigratingfrompreviousversionsofAPScheduler13
APSchedulerDocumentation,Release3.0.5
•Theshutdown_threadpoolandclose_jobstoresoptionshavebeenremovedfromtheshutdown()method.Executorsandjobstoresarenowalwaysshutdownonschedulershutdown.
•unschedule_job()andunschedule_func()havebeenreplacedbyremove_job().Youcanalsounscheduleajobbyusingthejobhandlereturnedfromadd_job().Jobstorechanges
Thejobstoresystemwascompletelyoverhauledforbothefficiencyandforwardscompatibility.Unfortunately,thismeansthattheolddataisnotcompatiblewiththenewjobstores.IfyouneedtomigrateexistingdatafromAPSched-uler2.xto3.x,contacttheAPSchedulerauthor.
TheShelvejobstorehadtobedroppedbecauseitcouldnotsupportthenewjobstoredesign.UseSQLAlchemyJob-StorewithSQLiteinstead.Triggerchanges
From3.0onwards,triggersnowrequireapytztimezone.Thisisnormallyprovidedbythescheduler,butifyouwereinstantiatingtriggersmanuallybefore,thenonemustbesuppliedasthetimezoneargument.
Theonlyotherbackwardsincompatiblechangewasthatget_next_fire_time()takestwoargumentsnow:thepreviousfiretimeandthecurrentdatetime.
1.3.2Fromv1.xto2.0
TherehavebeensomeAPIchangessincethe1.xseries.Thisdocumentexplainsthechangesmadetov2.0thatareincompatiblewiththev1.xAPI.APIchanges
•Thebehaviorofcronschedulingwithregardstodefaultvaluesforomittedfieldshasbeenmademoreintuitive–omittedfieldslowerthantheleastsignificantexplicitlydefinedfieldwilldefaulttotheirminimumvaluesexceptfortheweeknumberandweekdayfields
•SchedulerShutdownErrorhasbeenremoved–jobsarenowaddedtentativelyandscheduledforrealwhen/iftheschedulerisrestarted
•Scheduler.is_job_active()hasbeenremoved–usejobinscheduler.get_jobs()instead•dump_jobs()isnowprint_jobs()andprintsdirectlytothegivenfileorsys.stdoutifnoneisgiven
•Therepeatparameterwasremovedfromadd_interval_job()andinterval_schedule()infa-voroftheuniversalmax_runsoption
•unschedule_func()nowraisesaKeyErrorifthegivenfunctionisnotscheduled
•Thesemanticsofshutdown()havechanged–themethodnolongeracceptsanumericargument,buttwobooleans
Configurationchanges
•Theschedulercannolongerbereconfiguredwhileit’srunning
14Chapter1.TableofContents
APSchedulerDocumentation,Release3.0.5
1.4ContributingtoAPScheduler
IfyouwishtoaddafeatureorfixabuginAPScheduler,youneedtofollowcertainproceduresandrulestogetyourchangesaccepted.Thisistomaintainthehighqualityofthecodebase.
1.4.1ContributionProcess
1.ForktheprojectonBitBucket2.Clonetheforktoyourlocalmachine3.Makethechangestotheproject
4.Runthetestsuitewithtox(ifyouchangedanycode)5.Repeatsteps3-4untilthetestsuitepasses6.Commitifyouhaven’talready7.PushthechangestoyourBitBucketfork8.MakeapullrequestonBitBucket
Thereisnoneedtoupdatethechangelog–thiswillbedonepriortothenextreleaseatthelatest.Shouldthetestsuitefailevenbeforeyourchanges(whichshouldberare),makesureyou’reatleastnotaddingtothefailures.
1.4.2DevelopmentDependencies
Tofullyrunthetestsuite,youwillneedatleast:
•AMongoDBserver•ARedisserver
Forotherdependencies,it’sbesttolookintox.iniandinstallwhatisappropriateforthePythonversionyou’reusing.
1.4.3CodeStyle
ThisprojectusesPEP8ruleswithamaximumcolumnlimitof120charactersinsteadofthestandard79.Thislimitappliestoalltextfiles(sourcecode,tests,documentation).Inparticular,remembertogrouptheimportscorrectly(standardlibraryimportsfirst,thirdpartylibssecond,projectlibrariesthird,conditionalimportslast).ThePEP8checkerdoesnotcheckforthis.Ifindoubt,justfollowthesurroundingcodestyleascloselyaspossible.
1.4.4Testing
Runningthetestsuiteisdoneusingthetoxutility.ThiswilltestthecodebaseagainstallsupportedPythonversionsandchecksforPEP8violationsaswell.
SincerunningthetestsoneverysupportedPythonversioncantakequitealongtime,itisrecommendedthatduringthedevelopmentcyclepy.testisuseddirectly.Beforefinishing,toxshouldhoweverbeusedtomakesurethecodeworksonallsupportedPythonversions.
Anynontrivialcodechangesmustbeaccompaniedwiththeappropriatetests.Thetestsshouldnotonlymaintainthecoverage,butshouldtestanynewfunctionalityorbugfixesreasonablywell.Ifyou’refixingabug,firstmakesureyouhaveatestwhichfailsagainsttheunpatchedcodebaseandsucceedsagainstthefixedversion.Naturally,thetestsuitehastopassoneveryPythonversion.IfsettingupalltherequiredPythoninterpretersseemsliketoomuchtrouble,makesurethatitatleastpassesonthelowestsupportedversionsofbothPython2and3.1.4.ContributingtoAPScheduler
15
APSchedulerDocumentation,Release3.0.5
1.5ExtendingAPScheduler
Thisdocumentismeanttoexplainhowtodevelopyourcustomtriggers,jobstores,executorsandschedulers.
1.5.1Customtriggers
Thebuilt-intriggerscovertheneedsofthemajorityofallusers.However,someusersmayneedspecializedschedulinglogic.Tothatend,thetriggersystemwasmadepluggable.
Toimplementyourschedulinglogic,subclassBaseTrigger.Lookattheinterfacedocumentationinthatclass.Thenlookattheexistingtriggerimplementations.Thatshouldgiveyouagoodideawhatisexpectedofatriggerimplementation.
Touseyourtrigger,youcanuseadd_job()likethis:
trigger=MyTrigger(arg1='foo')scheduler.add_job(target,trigger)Youcanalsoregisteritasapluginsoyoucanusecanusethealternateformofadd_jobstore:
scheduler.add_job(target,'my_trigger',arg1='foo')Thisisdonebyaddinganentrypointinyourproject’ssetup.py:
...entry_points={'apscheduler.triggers':['my_trigger=mytoppackage.subpackage:MyTrigger']}1.5.2Customjobstores
IfyouwanttostoreyourjobsinafancynewNoSQLdatabase,oratotallycustomdatastore,youcanimplementyourownjobstorebysubclassingBaseJobStore.
AjobstoretypicallyserializestheJobobjectsgiventoit,andconstructsnewJobobjectsfrombinarydatawhentheyareloadedfromthebackingstore.Itisimportantthatthejobstorerestoresthe_schedulerand_jobstore_aliasattributeofanyJobthatitcreates.Refertoexistingimplementationsforexamples.
ItshouldbenotedthatMemoryJobStoreisspecialinthatitdoesnotdeserializethejobs.Thiscomeswithitsownproblems,whichithandlesinitsownway.Ifyourjobstoredoesserializejobs,youcanofcourseuseaserializerotherthanpickle.Youshould,however,usethe__getstate__and__setstate__specialmethodstorespectivelygetandsettheJobstate.Pickleusesthemimplicitly.Touseyourjobstore,youcanaddittotheschedulerlikethis:
jobstore=MyJobStore()scheduler.add_jobstore(jobstore,'mystore')Youcanalsoregisteritasapluginsoyoucanusecanusethealternateformofadd_jobstore:
scheduler.add_jobstore('my_jobstore','mystore')Thisisdonebyaddinganentrypointinyourproject’ssetup.py:
...entry_points={'apscheduler.jobstores':['my_jobstore=mytoppackage.subpackage:MyJobStore']}16Chapter1.TableofContents
APSchedulerDocumentation,Release3.0.5
1.5.3Customexecutors
Ifyouneedcustomlogicforexecutingyourjobs,youcancreateyourownexecutorclasses.Onescenarioforthiswouldbeifyouwanttousedistributedcomputingtorunyourjobsonothernodes.StartbysubclassingBaseExecutor.Theresponsibilitiesofanexecutorareasfollows:
•Performinganyinitializationwhenstart()iscalled•Releasinganyresourceswhenshutdown()iscalled
•Keepingtrackofthenumberofinstancesofeachjobrunningonit,andrefusingtorunmorethanthemaximum•Notifyingthescheduleroftheresultsofthejob
Ifyourexecutorneedstoserializethejobs,makesureyoueitherusepickleforit,orinvokethe__getstate__and__setstate__specialmethodstorespectivelygetandsettheJobstate.Pickleusesthemimplicitly.Touseyourexecutor,youcanaddittotheschedulerlikethis:
executor=MyExecutor()scheduler.add_executor(executor,'myexecutor')Youcanalsoregisteritasapluginsoyoucanusecanusethealternateformofadd_executor:
scheduler.add_executor('my_executor','myexecutor')Thisisdonebyaddinganentrypointinyourproject’ssetup.py:
...entry_points={'apscheduler.executors':['my_executor=mytoppackage.subpackage:MyExecutor']}1.5.4Customschedulers
Atypicalsituationwhereyouwouldwanttomakeyourownschedulersubclassiswhenyouwanttointegrateitwithyourapplicationframeworkofchoice.
YourcustomschedulershouldalwaysbeasubclassofBaseScheduler.Butifyou’renotadaptingtoaframeworkthatreliesoncallbacks,considersubclassingBlockingSchedulerinstead.Themosttypicalextensionpointsforschedulersubclassesare:
•start()mustbeoverriddentowakeuptheschedulerforthefirsttime
•shutdown()mustbeoverriddentoreleaseresourcesallocatedduringstart()
•wakeup()mustbeoverriddentomanagethetimernotifytheschedulerofchangesinthejobstore•_create_lock()overrideifyourframeworkusessomealternatelockingimplementation(likegevent)•_create_default_executor()overrideifyouneedtouseanalternativedefaultexecutor
Important:Remembertocallthesuperclassimplementationsofoverriddenmethods,evenabstractones(unlessthey’reempty).
Themostimportantresponsibilityoftheschedulersubclassistomanagethescheduler’ssleepingbasedonthereturnvaluesof_process_jobs().Thiscanbedoneinvariousways,includingsettingtimeoutsinwakeup()orrunningablockingloopinstart().Again,seetheexistingschedulerclassesforexamples.
1.5.ExtendingAPScheduler17
APSchedulerDocumentation,Release3.0.5
18Chapter1.TableofContents
CHAPTER2
Indicesandtables
•APIreference
19
APSchedulerDocumentation,Release3.0.5
20Chapter2.Indicesandtables
Index
P
PythonEnhancementProposals
PEP3156,1
21
因篇幅问题不能全部显示,请点此查看更多更全内容