详解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秒执行一次!
即:
到此这篇关于详解APScheduler如何设置任务不并发的文章就介绍到这了,更多相关APScheduler 任务不并发内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!
原文出处:https://geo-ai.blog.csdn.net/article/details/125565204
相关文章
- php5.3或以上版本可以使用php管理crontab计划任务,下面我先来体验一下,有需要学习了解的朋友可进入参考。 1.使用php-crontab-manager管理计划任务 要求 PHP>=5.3...2016-11-25
tomcat启动完成执行 某个方法 定时任务(Spring)操作
这篇文章主要介绍了tomcat启动完成执行 某个方法 定时任务(Spring)操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-25- 这篇文章主要通过一个小demo介绍了C#如何对多线程、多任务管理,需要的朋友可以参考下...2020-06-25
- c#并行任务多种优化方案分享,使用异步委托+回调函数方式实现,大家参考使用吧...2020-06-25
springboot定时任务@Scheduled执行多次的问题
这篇文章主要介绍了springboot定时任务@Scheduled执行多次问题的解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-10-18聊聊通过celery_one避免Celery定时任务重复执行的问题
Celery Once 也是利用 Redis 加锁来实现, Celery Once 在 Task 类基础上实现了 QueueOnce 类,该类提供了任务去重的功能,今天通过本文给大家介绍通过celery_one避免Celery定时任务重复执行的问题,感兴趣的朋友一起看看吧...2021-10-31- Web服务器执行一个PHP脚本,有时耗时很长才能返回执行结果,后面的脚本需要等待很长一段时间才能继续执行。如果想实现只简单触发耗时脚本的执行而不等待执行结果就直接执行下一步操作,可以通过fscokopen函数来实现。PHP支...2014-05-31
- 这篇文章主要介绍了Java并行执行任务的几种方案小结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-11-05
- 这篇文章主要介绍了Golang Cron 定时任务的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-05-11
- 这篇文章主要介绍了Python定义一个Actor任务,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-07-29
- 这篇文章主要介绍了PowerShell 远程执行任务的方法步骤,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-30
- 这篇文章主要介绍了详解PHP执行定时任务的几种实现思路,PHP的定时任务功能必须通过和其他工具结合才能实现,们就来深入的解析几种常见的php定时任务的思路...2015-12-24
- 所谓的任务调度是指安排任务的执行计划,即何时执行,怎么执行等。这篇文章主要介绍了Python任务调度利器之APScheduler详解,需要的朋友可以参考下...2020-05-10
- Apscheduler是基于Quartz的Python定时任务框架,功能上跟Quartz一致,使用上跟Quartz也几乎一致。下面通过本文给大家介绍Python定时库Apscheduler的简单使用,感兴趣的朋友一起看看吧...2021-11-13
- 这篇文章主要介绍了win2008中设置计划任务执行PHP文件的方法,需要的朋友可以参考下...2016-07-04
- 这篇文章主要为大家详细介绍了Spring定时任务,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助...2021-10-04
spring schedule配置多任务动态cron(增删启停)
这篇文章主要介绍了spring schedule配置多任务动态cron(增删启停),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-16如何在thinkphp中使用windows计划任务定时执行php文件
这篇文章主要介绍了如何在thinkphp中使用windows计划任务定时执行php文件,对定时执行感兴趣的同学,可以参考下...2021-04-21- 这篇文章主要介绍了调试WordPress中定时任务的相关PHP脚本示例,针对使用Cron API及wp_schedule_event()函数来写的定时任务,需要的朋友可以参考下...2015-12-14
- 在windows中如果你想让PHP程序自动运行那么我们必须使用windows计划任务来完成了,下面我来给各位同学介绍实现方法。 具体来说,我们若需利用任务计划程序自动运行则...2016-11-25