英文:
Pyhon APScheduler stop jobs before starting a new one
问题
我需要每30分钟启动一次任务,但在启动新任务之前,我希望终止旧任务,以确保任务始终获取到最新的数据文件,因为该文件会不断更新。
目前我正在使用BlockingScheduler以及自己的条件来停止任务(例如:如果处理了1k个数据等),我想知道APScheduler是否原生支持这种“同时只能运行一个任务,在启动新任务之前停止旧任务”的行为。
我已阅读了文档,但我认为最接近的情况仍然是默认行为,即max_instances=1,这只是防止在旧任务完成之前启动新任务,这不是我想要的。
感谢任何帮助!
英文:
I need to start a job every 30 minutes, but before a new job is being started I want the old but same job being terminated. This is to make sure the job always fetches the newest data file which is constantly being updated.
Right now I'm using the BlockingScheduler paired with my own condition to stop the job (stop job if processed 1k data etc.), I was wondering if APScheduler supports this "only 1 job at the same time and stop old one before new one" behavior natively
I've read the docs but I think the closest is still the default behavior which equals max_instances=1, this just prevents new jobs firing before the old job finishes, which is not what I'm looking for.
Any help is appreciated. Thanks!
答案1
得分: 0
经过进一步研究,我得出结论:APScheduler 并不原生支持这个功能,但受到 https://stackoverflow.com/questions/62435049/get-number-of-active-instances-for-backgroundscheduler-jobs 的启发,我修改了答案,实现了检测相同作业当前运行实例的数量的方法。因此,当您有一个无限循环/长时间任务正在执行,并且您希望新实例替换旧实例时,可以添加类似以下代码:
if(scheduler._executors['default']._instances['设置您喜欢的ID'] > 1):
# 如果有多个实例,中断循环/返回
return
当您启动时,代码应该如下所示:
scheduler = BlockingScheduler(timezone='Asia/Taipei')
scheduler.add_job(main,'cron', minute='*/30', max_instances=3, next_run_time=datetime.now(),\
id='设置您喜欢的ID')
scheduler.start()
但请像链接中的答案一样,在有一天出现原生方法时,请不要这样做。目前我正在使用的是 APScheduler 3.10 版本。
至少这种方法不依赖于在每次迭代中计算 time.now()
或 datetime.datetime.now()
来检查时间是否比循环开始时过去了多长时间。在我的情况下,由于我的作业每30分钟运行一次,我不想计算时间差,所以我选择了这种方法,希望这种独特的方法对于在谷歌上搜索了几天的人有所帮助。
英文:
After further research I came to a conclusion that this is not supported natively in APScheduler, but by inspired by
https://stackoverflow.com/questions/62435049/get-number-of-active-instances-for-backgroundscheduler-jobs
, I modified the answer into a working way of detecting the number of current running instances of the same job, so when you have a infinite loop/long task executing, and you want the new instance to replace the old instance, you can add something like
if(scheduler._executors['default']._instances['set_an_id_you_like'] > 1):
# if multiple instances break loop/return
return
and this is what should look like when you start:
scheduler = BlockingScheduler(timezone='Asia/Taipei')
scheduler.add_job(main,'cron', minute='*/30', max_instances=3, next_run_time=datetime.now(),\
id='set_an_id_you_like')
scheduler.start()
but like the answer in the link, please refrain from doing this if someday there's a native way to do this, currently I'm using APScheduler 3.10
This method at least doesn't rely on calculating time.now()
or datetime.datetime.now()
in every iteration to check if the time has passed compared when the loop started. In my case since my job runs every 30 minutes, I didn't want to calculate deltatime so this is what I went for, hope this hacky method helped someone that googled for a few days to come here.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论