• 售前

  • 售后

热门帖子
入门百科

python中BackgroundScheduler和BlockingScheduler的区别

[复制链接]
乔微博 显示全部楼层 发表于 2021-8-14 11:52:05 |阅读模式 打印 上一主题 下一主题
目次


  • 1、根本的定时调理
  • 2、BlockingScheduler与BackgroundScheduler区别
APScheduler最根本的用法: “定时几秒后启动job”
两种调理器: BackgroundScheduler和BlockingScheduler的区别,
job实行时间大于定时调理时间特别情况的问题及办理方法
每个job都会以thread的方式被调理。

1、根本的定时调理


APScheduler是python的一个定时使命调理框架,能实现雷同linux下crontab范例的使命,利用起来比较方便。它提供基于固定时间隔断、日期以及crontab配置雷同的使命调理,并可以持久化使命,或将使命以daemon方式运行。
下面是一个最根本的利用示例:
  1. from apscheduler.schedulers.blocking import BlockingScheduler
  2. def job():
  3.     print('job 3s')
  4. if __name__=='__main__':
  5.     sched = BlockingScheduler(timezone='MST')
  6.     sched.add_job(job, 'interval', id='3_second_job', seconds=3)
  7.     sched.start()
复制代码
它能实现每隔3s就调理job()运行一次,所以程序每隔3s就输出'job 3s'。通过修改add_job()的参数seconds,就可以改变使命调理的隔断时间。

2、BlockingScheduler与BackgroundScheduler区别


APScheduler中有很多种差异范例的调理器,BlockingScheduler与BackgroundScheduler是此中最常用的两种调理器。那他们之间有什么区别呢? 简朴来说,区别主要在于BlockingScheduler会阻塞主线程的运行,而BackgroundScheduler不会阻塞。所以,我们在差异的情况下,选择差异的调理器:
BlockingScheduler: 调用start函数后会阻塞当前线程。当调理器是你应用中唯一要运行的东西时(如上例)利用。
BackgroundScheduler: 调用start后主线程不会阻塞。当你不运行任何其他框架时利用,并盼望调理器在你应用的后台实行。
下面用两个例子来更直观的分析两者的区别。
BlockingScheduler例子
  1. from apscheduler.schedulers.blocking import BlockingScheduler
  2. import time
  3. def job():
  4.     print('job 3s')
  5. if __name__=='__main__':
  6.     sched = BlockingScheduler(timezone='MST')
  7.     sched.add_job(job, 'interval', id='3_second_job', seconds=3)
  8.     sched.start()
  9.     while(True): # 不会被执行到
  10.         print('main 1s')
  11.         time.sleep(1)
复制代码
运行这个程序,我们得到如下的输出:
  1. job 3s
  2. job 3s
  3. job 3s
  4. job 3s 
复制代码
可见,BlockingScheduler调用start函数后会阻塞当前线程,导致主程序中while循环不会被实行到。
BackgroundScheduler例子
  1. from apscheduler.schedulers.background import BackgroundScheduler
  2. import time
  3. def job():
  4.     print('job 3s')
  5. if __name__=='__main__':
  6.     sched = BackgroundScheduler(timezone='MST')
  7.     sched.add_job(job, 'interval', id='3_second_job', seconds=3)
  8.     sched.start()
  9.     while(True):
  10.         print('main 1s')
  11.         time.sleep(1)
复制代码
可见,BackgroundScheduler调用start函数后并不会阻塞当前线程,所以可以继续实行主程序中while循环的逻辑。
  1. main 1s
  2. main 1s
  3. main 1s
  4. job 3s
  5. main 1s
  6. main 1s
  7. main 1s
  8. job 3s 
复制代码
通过这个输出,我们也可以发现,调用start函数后,job()并不会立即开始实行。而是等待3s后,才会被调理实行。
怎样让job在start()后就开始运行
怎样才气让调理器调用start函数后,job()就立即开始实行呢?
实在APScheduler并没有提供很好的方法来办理这个问题,但有一种最简朴的方式,就是在调理器start之前,就运行一次job(),如下
  1. from apscheduler.schedulers.background import BackgroundScheduler
  2. import time
  3. def job():
  4.     print('job 3s')
  5. if __name__=='__main__':
  6.     job() # 执行一次就好了哟
  7.     sched = BackgroundScheduler(timezone='MST')
  8.     sched.add_job(job, 'interval', id='3_second_job', seconds=3)
  9.     sched.start()
  10.     while(True):
  11.         print('main 1s')
  12.         time.sleep(1)
复制代码
如许就能得到如下的输出
  1. job 3s
  2. main 1s
  3. main 1s
  4. main 1s
  5. job 3s
  6. main 1s
  7. main 1s
  8. main 1s
复制代码
如许固然没有绝对做到“让job在start()后就开始运行”,但也能做到“不等待调理,而是刚开始就运行job”。
假如job实行时间过长会怎么样
假如实行job()的时间须要5s,但调理器配置为每隔3s就调用一下job(),会发生什么情况呢?我们写了如下例子:
  1. from apscheduler.schedulers.background import BackgroundScheduler
  2. import time
  3. def job():
  4.     print('job 3s')
  5.     time.sleep(5)
  6. if __name__=='__main__':
  7.     sched = BackgroundScheduler(timezone='MST')
  8.     sched.add_job(job, 'interval', id='3_second_job', seconds=3)
  9.     sched.start()
  10.     while(True):
  11.         print('main 1s')
  12.         time.sleep(1)
复制代码
运行这个程序,我们得到如下的输出:
  1. main 1s
  2. main 1s
  3. main 1s
  4. job 3s
  5. main 1s
  6. main 1s
  7. main 1s
  8. Execution of job "job (trigger: interval[0:00:03], next run at: 2018-05-07 02:44:29 MST)" skipped: maximum number of running instances reached (1)
  9. main 1s
  10. main 1s
  11. main 1s
  12. job 3s
  13. main 1s
复制代码
可见,3s时间到达后,并不会“重新启动一个job线程”,而是会跳过该次调理,等到下一个周期(再等待3s),又重新调理job()。
为了能让多个job()同时运行,我们也可以配置调理器的参数max_instances,如下例,我们允许2个job()同时运行:
  1. from apscheduler.schedulers.background import BackgroundScheduler
  2. import time
  3. def job():
  4.     print('job 3s')
  5.     time.sleep(5)
  6. if __name__=='__main__':
  7.     job_defaults = { 'max_instances': 2 }
  8.     sched = BackgroundScheduler(timezone='MST', job_defaults=job_defaults)
  9.     sched.add_job(job, 'interval', id='3_second_job', seconds=3)
  10.     sched.start()
  11.     while(True):
  12.         print('main 1s')
  13.         time.sleep(1)
复制代码
运行程序,我们得到如下的输出:
  1. main 1smain 1smain 1sjob 3s
  2. main 1s
  3. main 1s
  4. main 1s
  5. job 3s
  6. main 1s
  7. main 1s
  8. main 1sjob 3s
复制代码
每个job是怎么被调理的

通过上面的例子,我们发现,调理器是定时调理job()函数,来实现调理的。
那job()函数会被以进程的方式调理运行,照旧以线程来运行呢?
为了弄清这个问题,我们写了如下程序:
  1. from apscheduler.schedulers.background import BackgroundScheduler
  2. import time,os,threading
  3. def job():
  4.     print('job thread_id-{0}, process_id-{1}'.format(threading.get_ident(), os.getpid()))
  5.     time.sleep(50)
  6. if __name__=='__main__':
  7.     job_defaults = { 'max_instances': 20 }
  8.     sched = BackgroundScheduler(timezone='MST', job_defaults=job_defaults)
  9.     sched.add_job(job, 'interval', id='3_second_job', seconds=3)
  10.     sched.start()
  11.     while(True):
  12.         print('main 1s')
  13.         time.sleep(1)
复制代码
运行程序,我们得到如下的输出:
  1. main 1s
  2. main 1s
  3. main 1s
  4. job thread_id-10644, process_id-8872
  5. main 1s
  6. main 1s
  7. main 1s
  8. job thread_id-3024, process_id-8872
  9. main 1s
  10. main 1s
  11. main 1s
  12. job thread_id-6728, process_id-8872
  13. main 1s
  14. main 1s
  15. main 1s
  16. job thread_id-11716, process_id-8872
复制代码
可见,每个job()的进程ID都雷同,但线程ID差异。所以,job()终极是以线程的方式被调理实行。
到此这篇关于python中BackgroundScheduler和BlockingScheduler的区别 的文章就先容到这了,更多相关python BackgroundScheduler BlockingScheduler内容请搜刮脚本之家从前的文章或继续浏览下面的相关文章盼望各人以后多多支持脚本之家!

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作