当前位置:网站首页>APScheduler如何设置任务不并发(即第一个任务执行完再执行下一个)?
APScheduler如何设置任务不并发(即第一个任务执行完再执行下一个)?
2022-07-04 05:34:00 【Jayce~】
APScheduler如何设置任务不并发(即第一个任务执行完再执行下一个)?
1.软件环境
Windows10 教育版64位
Python 3.6.3
APScheduler 3.6.3
2.问题描述
Python中定时任务的解决方案,总体来说有四种,分别是:crontab、 scheduler、 Celery、APScheduler,其中:
crontab是Linux的一个定时任务管理工具,在Windows上面有替代品pycron,但Windows不像Linux那样有很多强大的命令程序,pycron使用起来有局限性,定制性不好;Scheduler太过于简单、复杂一点的定时任务做起来太困难,特别是以月份以上时间单位的定时任务;Celery依赖的软件比较多,比较耗资源;APScheduler(Advanced Python Scheduler)基于Quartz,可以跨平台而且配置方便,提供了date、interval、cron3种不同的触发器,与Linux上原生的crontab格式兼容,可以设置任何高度复杂的定时任务,灵活的要死。
在此不介绍APScheduler的基本特性,有需要的可以直接去看APScheduler官方文档,我们直接切到主题:
APScheduler如何设置任务不并发(即第一个任务执行完再执行下一个)?
APScheduler在多个任务相同时间点同时被触发时,会同时并发执行多个任务,如使用下方的示例代码:
''' =========================================== @author: jayce @file: apscheduler设置任务不并发.py @time: 2022/7/1/001 19:38 =========================================== '''
from apscheduler.schedulers.blocking import BlockingScheduler
import time
def job_printer(text):
''' 死循环,用来模拟长时间执行的任务 :param text: :return: '''
while True:
time.sleep(2)
print("job text:{}".format(text))
if __name__ == '__main__':
schedule = BlockingScheduler()
schedule.add_job(job_printer, "cron", second='*/10', args=['每10秒执行一次!'])
schedule.add_job(job_printer, "cron", second='*/20', args=['每20秒执行一次!'])
schedule.print_jobs()
schedule.start()
可以看到,函数job_printer是一个死循环,用来模拟长时间执行的任务,我们使用add_job向APScheduler中添加2个job_printer,区别是2个任务的时间间隔为:每10秒执行一次和每20秒执行一次。
因为job_printer是一个死循环,相当于job_printer一直没有被执行完,但其实APScheduler在任务没有被执行完的情况下,同时执行多个不同的job_printer:
job text:每10秒执行一次!
job text:每20秒执行一次!
job text:每10秒执行一次!
job text:每20秒执行一次!
job text:每10秒执行一次!
job text:每20秒执行一次!
job text:每10秒执行一次!
job text:每20秒执行一次!
job text:每10秒执行一次!
Execution of job "job_printer (trigger: cron[second='*/10'], next run at: 2022-07-01 20:47:50 CST)" skipped: maximum number of running instances reached (1)
即:
可以看到10秒的job_printer和20秒的job_printer交替被执行,而其实10秒的job_printer其实根本没有执行完。这在CPU或者GPU等硬件设备能够承担负载的情况下,当然是好事,但如果你的硬件不够的话,发生OOM等资源不够的情况,程序就被中断了,导致你的模型训练或业务逻辑失败!具体的:
我这边是使用APScheduler和Tensorflow进行在线学习(online learning)时,在不同的时间节点下会对模型使用不一样的重训练方式,如有2个定时任务(A:每10秒执行一次,B:每20秒执行一次)和2种重训练方式(X和Y),当你的显存存在如下情况:
显存很少只够一个程序进行训练,不能多个程序同时运行,否则会
OOM;
那么只能引导程序依次执行,而不能并发执行,等当同一时间内X和Y同时被触发时,只执行其中1个,另外1个不执行。
那这个时候又该怎么办呢?
3.解决方法
通过查阅官方文档,发现可以通过设置执行任务的线程数,来控制只有1个执行器进行任务的执行,进而达到执行完任务X再执行任务Y,具体如下:
''' =========================================== @author: jayce @file: apscheduler设置任务不并发.py @time: 2022/7/1/001 19:38 =========================================== '''
from apscheduler.executors.pool import ThreadPoolExecutor
if __name__ == '__main__':
# 为了防止全量和增量并发造成显存溢出,进而训练失败,设置同一时间只能有一个任务运行
schedule = BlockingScheduler(executors={
'default': ThreadPoolExecutor(1)})
通过向BlockingScheduler设定最大的ThreadPoolExecutor=1,即可达到我们想要的效果!
4.结果预览
job text:每10秒执行一次!
job text:每10秒执行一次!
job text:每10秒执行一次!
job text:每10秒执行一次!
job text:每10秒执行一次!
Execution of job "job_printer (trigger: cron[second='*/10'], next run at: 2022-07-01 21:17:50 CST)" skipped: maximum number of running instances reached (1)
job text:每10秒执行一次!
job text:每10秒执行一次!
job text:每10秒执行一次!
job text:每10秒执行一次!
job text:每10秒执行一次!
Execution of job "job_printer (trigger: cron[second='*/10'], next run at: 2022-07-01 21:18:00 CST)" skipped: maximum number of running instances reached (1)
Execution of job "job_printer (trigger: cron[second='*/20'], next run at: 2022-07-01 21:18:00 CST)" skipped: maximum number of running instances reached (1)
即:
可以看到,一直在执行第1个被触发的任务,相同时间被触发的任务都被skipped了~~
当然,如果你想要第1个任务执行完时,执行被跳过的任务,可以通过在add_job中设置misfire_grace_time实现!
FAQ
1.APScheduler如果某个任务挂掉了,整个定时任务程序会中断吗?还是下次时间继续执行该任务?
答案是:程序不会中断,到下次执行任务的时间点,还会重新执行。
具体的,使用如下测试代码:
''' =========================================== @author: jayce @file: apscheduler设置任务不并发.py @time: 2022/7/1/001 19:38 =========================================== '''
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.executors.pool import ThreadPoolExecutor
import time
def exception_maker():
''' 异常制造器,用来模拟任务执行被中断 :return: '''
return 1 / 0
def job_printer(text):
''' 死循环,用来模拟长时间执行的任务 :param text: :return: '''
while True:
time.sleep(2)
print("job text:{}".format(text))
if __name__ == '__main__':
schedule = BlockingScheduler()
schedule.add_job(job_printer, "cron", second='*/10', args=['每10秒执行一次!'])
schedule.add_job(exception_maker, "cron", second='*/5')
schedule.print_jobs()
schedule.start()
可以看到exception_maker已经失败多次,但是不影响其他任务和它自身的下次执行:
Job "exception_maker (trigger: cron[second='*/5'], next run at: 2022-07-01 19:53:30 CST)" raised an exception
Traceback (most recent call last):
File "C:\Users\Jayce\Anaconda3\envs\tf2.3\lib\site-packages\apscheduler\executors\base.py", line 125, in run_job
retval = job.func(*job.args, **job.kwargs)
File "E:/Code/Python/demo代码/apscheduler设置任务不并发.py", line 14, in exception_maker
return 1 / 0
ZeroDivisionError: division by zero
Job "exception_maker (trigger: cron[second='*/5'], next run at: 2022-07-01 19:53:35 CST)" raised an exception
Traceback (most recent call last):
File "C:\Users\Jayce\Anaconda3\envs\tf2.3\lib\site-packages\apscheduler\executors\base.py", line 125, in run_job
retval = job.func(*job.args, **job.kwargs)
File "E:/Code/Python/demo代码/apscheduler设置任务不并发.py", line 14, in exception_maker
return 1 / 0
ZeroDivisionError: division by zero
job text:每10秒执行一次!
job text:每10秒执行一次!
Job "exception_maker (trigger: cron[second='*/5'], next run at: 2022-07-01 19:53:40 CST)" raised an exception
Traceback (most recent call last):
File "C:\Users\Jayce\Anaconda3\envs\tf2.3\lib\site-packages\apscheduler\executors\base.py", line 125, in run_job
retval = job.func(*job.args, **job.kwargs)
File "E:/Code/Python/demo代码/apscheduler设置任务不并发.py", line 14, in exception_maker
return 1 / 0
ZeroDivisionError: division by zero
job text:每10秒执行一次!
job text:每10秒执行一次!
Execution of job "job_printer (trigger: cron[second='*/10'], next run at: 2022-07-01 19:53:40 CST)" skipped: maximum number of running instances reached (1)
Job "exception_maker (trigger: cron[second='*/5'], next run at: 2022-07-01 19:53:45 CST)" raised an exception
Traceback (most recent call last):
File "C:\Users\Jayce\Anaconda3\envs\tf2.3\lib\site-packages\apscheduler\executors\base.py", line 125, in run_job
retval = job.func(*job.args, **job.kwargs)
File "E:/Code/Python/demo代码/apscheduler设置任务不并发.py", line 14, in exception_maker
return 1 / 0
ZeroDivisionError: division by zero
job text:每10秒执行一次!
即:
都看到这里了,还不赶紧点赞,评论,收藏走一波?
边栏推荐
- js arguments参数使用和详解
- 一键过滤选择百度网盘文件
- [microservice] Nacos cluster building and loading file configuration
- 注释与注解
- 复合非线性反馈控制(二)
- BUU-Crypto-Cipher
- The data mark is a piece of fat meat, and it is not only China Manfu technology that focuses on this meat
- 光模塊字母含義及參數簡稱大全
- Halcon图片标定,使得后续图片处理过后变成与模板图片一样
- VB.net GIF(制作、拆解——优化代码,类库——5)
猜你喜欢
随机推荐
Appearance of LabVIEW error dialog box
BUU-Crypto-[HDCTF2019]basic rsa
Flink1.13 SQL basic syntax (I) DDL, DML
fastjson
如何判断数组中是否含有某个元素
力扣(LeetCode)184. 部门工资最高的员工(2022.07.03)
如何展开Collapse 的所有折叠面板
Halcon图片标定,使得后续图片处理过后变成与模板图片一样
Wechat applet +php realizes authorized login
How to get the parent node of all nodes in El tree
Nodejs learning document
win10清除快速访问-不留下痕迹
2022 R2 mobile pressure vessel filling retraining question bank and answers
Luogu deep foundation part 1 Introduction to language Chapter 5 array and data batch storage
Google Chrome browser will support the function of selecting text translation
基于单片机的太阳能杀虫系统
VB.net 简单的处理图片,黑白(类库——7)
Programmers don't talk about morality, and use multithreading for Heisi's girlfriend
LM small programmable controller software (based on CoDeSys) note XXI: error 3703
C language simple student management system (including source code)









