Python Flask_APScheduler定时使命的精确(最佳)使用

打印 上一主题 下一主题

主题 552|帖子 552|积分 1656

描述 

APScheduler基于Quartz的一个Python定时使命框架,实现了Quartz的所有功能。最近使用Flask框架使用Flask_APScheduler来做定时使命,在使用过程当中也遇到很多问题,例如在定时使命调用的方法中需要用到flask的app.app_context()时,需要使用current_app记载日志时,例如:current_app.logger.info("my_job已实行"),定时使命中使用current_app对象会报错,查看了很多资料,大部分资料都是说没有app就创建一个,这样确实也能解决,但是我总感觉这种解决是有问题的,拿.Net Core来说,使用Quartz.NET定时使命时,定时使命依赖于一个Host(主机)对象,不需要重复创建Host对象,但是Flask的app对象使用过程中却需要重新create app,Quartz.NET也是基于Quartz的定时使命框架,我使用过Quartz.NET,因此始终觉得Flask_APScheduler中create app使用是有问题,终于在过了一段时间后看到一位先辈使用Flask_APScheduler的一篇文章后,刹时通达了,这个问题终于得到完美解决
 最佳使用Flask_APScheduler

 安装Flask_APScheduler

  1. pip install Flask_APScheduler
复制代码
1.项目结构图如下:

 
 2.Python 软件包utils下的__init__.py 初始化生成APScheduler对象

这里可以机动处理,例如:也可以是common软件包下__init__.py里初始化APScheduler
 __init__.py的代码如下:
  1. import atexit
  2. import platform
  3. from flask_apscheduler import APScheduler
  4. # 初始化生成APScheduler对象
  5. scheduler = APScheduler()
  6. def init_scheduler(app):
  7.     # 解决APScheduler定时任务重复执行的问题
  8.     if platform.system() == 'Linux':
  9.         # Linux 环境下
  10.         fcntl = __import__("fcntl")
  11.         f = open('scheduler.lock', 'wb')
  12.         try:
  13.             fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
  14.             scheduler.init_app(app)
  15.             scheduler.start()
  16.         except Exception as e:
  17.             app.logger.error(e)
  18.             print(e)
  19.         def unlock():
  20.             fcntl.flock(f, fcntl.LOCK_UN)
  21.             f.close()
  22.         atexit.register(unlock)
  23.     else:
  24.         # Window 环境下
  25.         msvcrt = __import__('msvcrt')
  26.         f = open('scheduler.lock', 'wb')
  27.         try:
  28.             msvcrt.locking(f.fileno(), msvcrt.LK_NBLCK, 1)
  29.             scheduler.init_app(app)
  30.             scheduler.start()
  31.         except Exception as e:
  32.             pass
  33.         def _unlock_file():
  34.             try:
  35.                 f.seek(0)
  36.                 msvcrt.locking(f.fileno(), msvcrt.LK_UNLCK, 1)
  37.             except Exception as e:
  38.                 pass
  39.         atexit.register(_unlock_file)
复制代码
3. config.py设置类代码

  1. class Config:
  2.     JOBS = [
  3.         {
  4.             'id': 'job1',
  5.             'func': 'app:MyService.my_job',  # 注意这里的格式,app 是 Flask 应用对象的名称(app.py),: 后面是任务函数名
  6.             'kwargs': {'job_name': 'job1'},
  7.             'trigger': 'cron',
  8.             'hour': 16,  # 16 点执行
  9.             'minute': 58,  # 58 分执行
  10.             'second': 0  # 0 秒执行
  11.         },
  12.         {
  13.             'id': 'job2',
  14.             'func': 'app:MyService.my_job',  # 注意这里的格式,app 是 Flask 应用对象的名称(app.py),: 后面是任务函数名
  15.             'kwargs': {'job_name': 'job2'},
  16.             'trigger': 'cron',
  17.             'hour': 16,  # 16 点执行
  18.             'minute': 58,  # 58 分执行
  19.             'second': 3  # 3 秒执行
  20.         },
  21.         {
  22.             'id': 'job3',
  23.             'func': 'app:MyService.my_job',  # 注意这里的格式,app 是 Flask 应用对象的名称(app.py),: 后面是任务函数名
  24.             'kwargs': {'job_name': 'job3'},
  25.             'trigger': 'cron',
  26.             'hour': 16,  # 16 点执行
  27.             'minute': 58,  # 58 分执行
  28.             'second': 6  # 6 秒执行
  29.         }
  30.     ]
  31.     # 开启API功能,这样才可以用api的方式去查看和修改定时任务
  32.     SCHEDULER_API_ENABLED = True
复制代码
4.app.py中代码如下 

  1. from config.config import Config  # 导入Config类的配置
  2. from utils import init_scheduler  # 导入init_scheduler方法
  3. # 创建Flask应用
  4. app = Flask(__name__)
  5. app.config.from_object(Config)  # 读取Config类的配置
  6. init_scheduler(app)  # init_scheduler方法
复制代码
5. MyService类中的my_job的方法使用app上下文

  1. from flask import current_app  # 导入flask的current_app(当前app)
  2. from utils import scheduler  # 很关键的一步 导入utils.__init__.py 初始化后的scheduler对象
  3. class MyService:
  4.     @classmethod
  5.     def my_job(cls, job_name):
  6.         # # # 此方法在定时任务多的情况下,会有性能问题,少的情况没啥问题
  7.         # app = create_app()
  8.         # with app.app_context():
  9.         #     current_app.logger.info("my_job已执行")
  10.         # #     print(f"my_job,当前时间{datetime.now()}")
  11.         # # 使用全局APP变量
  12.         # get_app()
  13.         # with APP.app_context():
  14.         #     current_app.logger.info(f"{job_name}已执行")
  15.         #     print(f"my_job,当前时间{datetime.now()}")
  16.         with scheduler.app.app_context():   # 这个sheduler是带有app及其上下文的
  17.             current_app.logger.info(f"{job_name}已执行")
复制代码
不建议使用 创建一个app的方法
create app的链接:https://blog.csdn.net/weixin_41934979/article/details/140406152 
6.实行效果如下: 


 源代码地址:https://gitee.com/jxzcode_admin/flask-project.git
 7.总结

 使用的Python 软件包下的__init__.py文件中初始化生成scheduler对象,此对象项目启动后只生成一次,然后导入scheduler对象,在定时使命实行的方法使用: with scheduler.app.app_context(): 就可以 获取flask当前app上下文,不需要create app,个人觉得这才是真正精确使用Flask_APScheduler
 参考资料
https://blog.csdn.net/arnolan/article/details/84936075
https://www.jianshu.com/p/d5a46b2d2fd3

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用户云卷云舒

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表