因为APScheduler的CronTrigger的DayOfMonthField本身无法匹配表达式last-n,所以需要进行改造。先放源码:classDayOfMonthField(BaseField):COMPILERS=BaseField.COMPILERS+[WeekdayPositionExpression,LastDayOfMonthExpression]defget_max(self,dateval):returnmonthrange(dateval.year,dateval.month)[1]这里,BaseField.COMPILERS,WeekdayPositionExpression,LastDayOfMonthExpression用于匹配表达式,然后取值。例如,LastDayOfMonthExpression:classLastDayOfMonthExpression(AllExpression):value_re=re.compile(r'last',re.IGNORECASE)def__init__(self):super(LastDayOfMonthExpression,self).__init__(None)defget_next_value(self,date,field):returnmonthrange(date.year,date.month)[1]def__str__(self):return'last'def__repr__(self):return"%s()"%self.__class__.__name__匹配最后一个,然后通过get_next_value获取要执行的值。那么我们要做的就是修改正则表达式:fromapscheduler.triggers.cron.expressionsimportAllExpressionclassLastNDayOfMonthExpression(AllExpression):value_re=re.compile(r'last(-\d+)?',re.IGNORECASE)def__init__(self):super(LastNDayOfMonthExpression,self).__init__(None)defget_next_value(self,date,field):_expr=self.value_re.match(field.exprs).group(1)day=monthrange(date.year,date.month)[1]if_expr:day-=int(_expr[1:])返回日期def__str__(self):return'last-n'def__repr__(self):return"%s()"%self.__class__.__name__然后将其替换掉LastDayOfMonthExpression就进行了importrefromcalendarimportmonthrangefromapscheduler.triggers.cronimportCronTriggeras_CronTrigger,DayOfMonthFieldas_DayOfMonthField,BaseFieldfromapscheduler.triggers.cron.expressionsimportAllExpression,WeekdayPositionExpressionclassDayOfMonthField(_DayOfMonthField):编译器=BaseField.COMPILERS+[WeekdayPositionExpression,LastNDayOfMonthExpression]def__init.exprs__(self,name,exprsFalse)=表达式super().__init__(name,exprs,is_default=is_default)classCronTrigger(_CronTrigger):_CronTrigger.FIELDS_MAP.update({'day':DayOfMonthField})这样我们就成功改造了CronTrigger,很简单投入使用fromapscheduler.schedulers.backgroundimportBackgroundScheduleras_BackgroundSchedulerfromutils.schedulerimportCronTriggerclassBackgroundScheduler(_BackgroundScheduler):_trigger_classes={'cron':CronTrigger}最后,我们可以在创建BackgroundScheduler调度器时使用自己的修改,是不是'是不是很简单?
