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
、cron
3种不同的触发器,与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秒执行一次!
即:
都看到这里了,还不赶紧 点赞
, 评论
, 收藏
走一波?
Original: https://blog.csdn.net/qq_15969343/article/details/125565204
Author: 任博今天就要毕业
Title: APScheduler如何设置任务不并发(即第一个任务执行完再执行下一个)?
相关阅读
Title: (保姆教程)Spyder 配置Tensorflow(2.5.0)和keras(2.4.3)
(保姆教程)Spyder 配置Tensorflow(2.5.0)和keras(2.4.3)
前言
其实安装Tensorflow和keras的过程不难,但是寻找匹配的版本,以及使得Spyder适应花了自己很长时间!
安装Tensorflow
打开anaconda prompt
; 首先查看自己的python版本
python --version
接着创建一个新的环境
conda create -n tf python=3.9.7
进入这个环境
conda activate tf
安装Tensorflow
pip install tensorflow==2.5.0
安装Keras
首先输入以下两行代码()
conda install mingw libpython
pip install theano
安装对应的Keras(版本一定要对应)
pip install keras==2.4.3
适应Spyder
在安装完成之后打开Spyder会发现其实用的解释器还是base,这个时候我们需要切换到tf中的python.exe解释器,但是切换之后重启内核,会显示内核错误!
解决:
这个时候需要我们先在刚才的命令行中输入
conda install spyder
重新安装spyder,再次打开会发现可以正常运行
输入以下代码测试
import keras
from keras.datasets import mnist
(train_images,train_labels),(test_images,test_labels) = mnist.load_data()
print('shape of train images is ',train_images.shape)
print('shape of train labels is ',train_labels.shape)
print('train labels is ',train_labels)
print('shape of test images is ',test_images.shape)
print('shape of test labels is',test_labels.shape)
print('test labels is',test_labels)
成功运行!
但美中不足的是,使用tensorflow之后之前conda自带的很多库就用不了了,需要重新pip或者conda
Original: https://blog.csdn.net/qq_43102225/article/details/124833331
Author: skyoung13
Title: (保姆教程)Spyder 配置Tensorflow(2.5.0)和keras(2.4.3)

tf 随机种子固定

带你看懂变分自编码(VAE)

实现简单的中英互译的安卓App

kaldi下L.fst可视化fstprint失败,报错Bad FST header: ../lang/L.fst

Out of memory error on GPU 0. Cannot allocate xxxGB memory on GPU 0, available memory is only xxx

使用realsense t265测试svo2.0视觉里程计

遥感影像语义分割论文笔记(一)FarSeg CVPR2020

Tensorflow:AttributeError: module ‘tensorflow’ has no attribute ‘contrib’解决方案

计算机视觉有关期刊56个(进入计算机前200)

Python3安装tensorflow

微信语音怎么转发给别人听_微信收到的语音如何转给别人?试试这2个方法,没准能帮到你…

RNNoise降噪训练

YOLOv5更换激活函数(FReLU+SE机制)

制作YOLOv5数据集
