脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Python - 详解APScheduler如何设置任务不并发

详解APScheduler如何设置任务不并发

2022-07-19 15:33Jayce~ Python

本文主要介绍了APScheduler如何设置任务不并发,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1.软件环境

Windows10 教育版64位
Python 3.6.3
APScheduler 3.6.3

2.问题描述

Python中定时任务的解决方案,总体来说有四种,分别是:crontabschedulerCeleryAPScheduler,其中:

  • crontab是 Linux 的一个定时任务管理工具,在Windows上面有替代品pycron,但Windows不像 Linux那样有很多强大的命令程序,pycron使用起来有局限性,定制性不好;
  • Scheduler太过于简单、复杂一点的定时任务做起来太困难,特别是以月份以上时间单位的定时任务;
  • Celery依赖的软件比较多,比较耗资源;
  • APScheduler(Advanced Python Scheduler) 基于 Quartz,可以跨平台而且配置方便,提供了date、interval、cron3种不同的触发器,与Linux上原生的 crontab 格式兼容,可以设置任何高度复杂的定时任务,灵活的要死。

在此不介绍APScheduler的基本特性,有需要的可以直接去看APScheduler官方文档,我们直接切到主题:

APScheduler如何设置任务不并发(即第一个任务执行完再执行下一个)?

APScheduler在多个任务相同时间点同时被触发时,会同时并发执行多个任务,如使用下方的示例代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
'''
===========================================
  @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_jobAPScheduler中添加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)

即:

详解APScheduler如何设置任务不并发

可以看到10秒的job_printer和20秒的job_printer交替被执行,而其实10秒的job_printer其实根本没有执行完。这在CPU或者GPU等硬件设备能够承担负载的情况下,当然是好事,但如果你的硬件不够的话,发生OOM等资源不够的情况,程序就被中断了,导致你的模型训练或业务逻辑失败!
具体的
我这边是使用APSchedulerTensorflow进行在线学习(online learning)时,在不同的时间节点下会对模型使用不一样的重训练方式,如有2个定时任务(A:每10秒执行一次,B:每20秒执行一次)和2种重训练方式(XY),当你的显存存在如下情况:

显存很少只够一个程序进行训练,不能多个程序同时运行,否则会OOM

那么只能引导程序依次执行,而不能并发执行,等当同一时间内XY同时被触发时,只执行其中1个,另外1个不执行。

那这个时候又该怎么办呢

3.解决方法

通过查阅官方文档,发现可以通过设置执行任务的线程数,来控制只有1个执行器进行任务的执行,进而达到执行完任务X再执行任务Y,具体如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
'''
===========================================
  @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)

即:

详解APScheduler如何设置任务不并发

可以看到,一直在执行第1个被触发的任务,相同时间被触发的任务都被skipped了~~
当然,如果你想要第1个任务执行完时,执行被跳过的任务,可以通过在add_job中设置misfire_grace_time实现!

FAQ

1.APScheduler如果某个任务挂掉了,整个定时任务程序会中断吗?还是下次时间继续执行该任务?

答案是:程序不会中断,到下次执行任务的时间点,还会重新执行。
具体的,使用如下测试代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
'''
===========================================
  @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如何设置任务不并发的文章就介绍到这了,更多相关APScheduler 任务不并发内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://geo-ai.blog.csdn.net/article/details/125565204

延伸 · 阅读

精彩推荐
  • Python利用Python如何制作贪吃蛇及AI版贪吃蛇详解

    利用Python如何制作贪吃蛇及AI版贪吃蛇详解

    这篇文章主要给大家介绍了关于利用Python如何制作贪吃蛇及AI版贪吃蛇的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的...

    不是孜然的孜然4092020-08-25
  • PythonPython中栈的详细介绍

    Python中栈的详细介绍

    这篇文章主要介绍的是Python中栈,栈(stacks)是一种只能通过访问其一端来实现数据存储与检索的线性数据结构,具有后进先出(last in first out,LIFO)的特征,下...

    李和龙11732022-03-03
  • Pythonpython实现诗歌游戏(类继承)

    python实现诗歌游戏(类继承)

    这篇文章主要为大家详细介绍了python实现诗歌游戏,根据上句猜下句、猜作者、猜朝代、猜诗名,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    我是李玉峰7882021-06-02
  • PythonPython 利用scrapy爬虫通过短短50行代码下载整站短视频

    Python 利用scrapy爬虫通过短短50行代码下载整站短视频

    近日,有朋友向我求助一件小事儿,他在一个短视频app上看到一个好玩儿的段子,想下载下来,可死活找不到下载的方法。经过我的一番研究才找到解决方...

    马鸣谦8222021-04-14
  • Pythonpython爬虫线程池案例详解(梨视频短视频爬取)

    python爬虫线程池案例详解(梨视频短视频爬取)

    这篇文章主要介绍了python爬虫线程池案例详解(梨视频短视频爬取),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值...

    小王子爱上玫瑰9172021-09-06
  • PythonPython实现的对本地host127.0.0.1主机进行扫描端口功能示例

    Python实现的对本地host127.0.0.1主机进行扫描端口功能示例

    这篇文章主要介绍了Python实现的对本地host127.0.0.1主机进行扫描端口功能,可实现扫描本机开放端口的功能,涉及Python socket模块与Thread多线程模块相关使用技巧...

    徐为波12142021-05-28
  • Python用Python实现筛选文件脚本的方法

    用Python实现筛选文件脚本的方法

    今天小编就为大家分享一篇用Python实现筛选文件脚本的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    林下的码路12602021-04-13
  • Pythonpython绘制直方图和密度图的实例

    python绘制直方图和密度图的实例

    今天小编就为大家分享一篇python绘制直方图和密度图的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    ColiYin7832021-08-04