flask_apscheduler实现定时推送飞书消息

news2024/11/16 4:41:49

需求场景:

  实现一个flask服务,通过接口控制一个定时任务任务(对酒店订房情况进行检查)的开启和停止。要求定时任务完成后,可以通过飞书机器人推送任务完成的消息。

展现效果:

  1. 启动定时任务
    在这里插入图片描述

  2. 关闭定时任务
    在这里插入图片描述

  3. 飞书推送消息
    在这里插入图片描述

代码实现:

  1. 项目结构:
    在这里插入图片描述

  2. 业务代码:

    1. 定时任务。先通过schedule模块实现基础的定时任务业务代码。

      # -*- coding:UTF-8 -*-
      
      """
       @ProjectName  : 
       @FileName     : schedule_monitor_task
       @Description  : 
       @Time         : 2023/9/18 9:21
       @Author       : Qredsun
       """
      import os
      import time
      from datetime import datetime
      from datetime import timedelta
      
      import schedule
      import functools
      from utils.webhook import send_message
      
      
      def read_check_list_from_excel(file):
          try:
             logger.info("业务代码")
          except Exception as e:
              logger.error(f'程序异常:{e}')
          finally:
              prompt_message = f'**酒店订房检查已完成**\n' \
                               f'检查时间:{begin_time} - {end_time} \n' \
                               f'检查报告已生成: {save_path}'
              send_message(Environment.WEBHOOK_URL, Environment.WEBHOOK_SECRET, prompt_message)
      
      
      # todo  定时任务配置
      def catch_exceptions(cancel_on_failure = False):
          def catch_exceptions_decorator(job_func):
              @functools.wraps(job_func)
              def wrapper(*args, **kwargs):
                  try:
                      return job_func(*args, **kwargs)
                  except:
                      import traceback
                      traceback.format_exc()
                      if cancel_on_failure:
                          return schedule.CancelJob
      
              return wrapper
      
          return catch_exceptions_decorator
      
      
      # 异常捕获方法的使用
      @catch_exceptions(cancel_on_failure=False)
      def task_job(file_path):
          # 定时任务
          read_check_list_from_excel(file_path)
      
      file_path = r'../data/订房检查任务.xlsx'
      schedule.every().day.at("09:00").do(task_job, file_path)
      schedule.run_all()
      
      while True:
          schedule.run_pending()  # 运行所有可以运行的任务
          time.sleep(60 * 30)
      
    2. 飞书消息推送功能实现

      # -*- coding:UTF-8 -*-
      
      """
       @ProjectName  : 
       @FileName     : webhook
       @Description  : 飞书消息推送
       @Time         : 2023/9/17 13:36
       @Author       : Qredsun
       """
      import base64
      import hashlib
      import hmac
      import json
      from datetime import datetime
      
      import requests
      
      from utils.env_manager import Environment, logger
      
      WEBHOOK_URL = '机器人推送地址'
      WEBHOOK_SECRET = '机器人密码'
      
      
      def gen_sign(secret, timestamp):
          # 拼接时间戳以及签名校验
          string_to_sign = '{}\n{}'.format(timestamp, secret)
      
          # 使用 HMAC-SHA256 进行加密
          hmac_code = hmac.new(
                  string_to_sign.encode("utf-8"), digestmod=hashlib.sha256
          ).digest()
      
          # 对结果进行 base64 编码
          sign = base64.b64encode(hmac_code).decode('utf-8')
      
          return sign
      
      
      def send_message(WEBHOOK_URL, WEBHOOK_SECRET, MSG):
          timestamp = int(datetime.now().timestamp())
          sign = gen_sign(WEBHOOK_SECRET, timestamp)
          params = {
              "timestamp": timestamp,
              "sign"     : sign,
              "msg_type" : "interactive",
              "card"     : {
                  "config"   : {
                      "wide_screen_mode": True
                  },
                  "elements" : [
                      {
                          "tag"    : "markdown",
                          "content": f"<at id=all></at> \n "
                                     f"{MSG}"
                      },
                      {
                          "tag"    : "action",
                          "actions": [
                              {
                                  "tag"      : "button",
                                  "text"     : {
                                      "tag"    : "plain_text",
                                      "content": "跳转至订房检查"
                                  },
                                  "type"     : "primary",
                                  "multi_url": {
                                      "url"        : Environment.CALL_BACK_URL,
                                      "android_url": "",
                                      "ios_url"    : "",
                                      "pc_url"     : ""
                                  }
                              }
                          ]
                      }
                  ],
                  "header"   : {
                      "template": "blue",
                      "title"   : {
                          "content": "订房检查异常提示",
                          "tag"    : "plain_text"
                      }
                  },
                  "card_link": {
                      "url"        : "",
                      "pc_url"     : "",
                      "android_url": "",
                      "ios_url"    : ""
                  }
              },
          }
      
          resp = requests.post(WEBHOOK_URL, json=params)
          resp.raise_for_status()
          result = resp.json()
          if result.get("code") and result.get("code") != 0:
              logger.error(f'飞书机器人消息 : {MSG} 发送失败:{resp.text}')
          else:
              logger.debug(f'飞书机器人消息 : {MSG} 发送成功')
      
    3. flask_apscheduler替换schedule

      app.schedule_job.add_job(id="check_room", func='s_app:read_check_list_from_excel', **{
          "args"   : (Environment.SRC_FILE,),
          # 'trigger': 'interval',  # 指定 定时任务的类型
          # 'seconds': 5  # 运行的间隔时间
      
          # 每天九点开始执行
          'trigger': 'cron',
          'day'    : '*',
          'hour'   : '09',
          'minute' : '00',
          'second' : '00'
      })
      app.schedule_job.start()  # 启动任务列表
      
    4. flask服务中启动、停止接口实现

      from flask import Flask
      
      from utils.env_manager import Environment, logger
      from utils.schedule_monitor_task import read_check_list_from_excel
      from flask_apscheduler import APScheduler
      
      app = Flask(__name__)
      app.schedule_job = APScheduler()
      
      
      @app.route('/', methods=['get'])
      def hello_world():
          return '酒店订房检查服务!'
      
      
      @app.route('/stop', methods=['get'])
      def stop_job():
          if not app.schedule_job.get_jobs():
              return '没有正在执行的订房检查任务'
          else:
              app.schedule_job.remove_all_jobs()
              return '终止订房检查任务'
      
      
      class Config(object):
          DEBUG = True  # flask 调试模式
          """flask_apscheduler 配置"""
          SCHEDULER_API_ENABLED = True  # 开放API
          SCHEDULER_TIMEZONE = 'Asia/Shanghai'  # 使用上海时间
      
      
      @app.route('/start', methods=['get'])
      def start_job():
          if app.schedule_job.get_jobs():
              return '订房检查任务已启动'
          else:
              app.schedule_job.add_job(id="check_room", func='s_app:read_check_list_from_excel', **{
                  "args"   : (Environment.SRC_FILE,)
                  # 每天九点开始执行
                  'trigger': 'cron',
                  'day'    : '*',
                  'hour'   : '09',
                  'minute' : '00',
                  'second' : '00'
              })
              return '开始订房检查任务'
      
      
      app.config.from_object(Config)
      app.schedule_job.init_app(app)  # 把任务列表放入 flask
      app.schedule_job.start()  # 启动任务列表
      app.run()
      
      

ps:

  • 机器人推送接口的配置:
    在这里插入图片描述

  • 在flask的配置中将SCHEDULER_API_ENABLED设置为True,服务启动后自动加载flask_apscheduler提供的API接口:
    1. /scheduler [GET] > 获取服务基本信息
    2. /scheduler/jobs [POST json job data] > 添加新的任务
    3. /scheduler/jobs/<job_id> [GET] > 根据job_id返回任务的详细信息
    4. /scheduler/jobs [GET] > 返回所有任务的信息
    5. /scheduler/jobs/<job_id> [DELETE] > 删除任务
    6. /scheduler/jobs/<job_id> [PATCH json job data] > 更新一个已经存在的任务
    7. /scheduler/jobs/<job_id>/pause [POST] > 暂停一个任务并返回任务的信息
    8. /scheduler/jobs/<job_id>/resume [POST] > 重新启动一个任务并返回任务信息
    9. /scheduler/jobs/<job_id>/run [POST] > 启动一个任务并返回任务的信息
    在这里插入图片描述

  • 在实现定时任务的启动和关闭时,并没有直接flask_apscheduler使用自带的接口,而是通过flask_apscheduler提供的定时任务管理方法实现。还有下面一些方法可参考使用:

    1. scheduler.start() 开始任务
    2. scheduler.shutdown() 停止任务
    3. scheduler.pause() 暂停所有任务
    4. scheduler.resume() 开启任务
    5. scheduler.add_listener(<callback function>,<event>) 添加监听事件
    6. scheduler.remove_listener(<callback function>) 去除监听事件
    7. scheduler.add_job(<id>,<function>, **kwargs) 添加job
    8. scheduler.remove_job(<id>, **<jobstore>) 删除job
    9. scheduler.remove_all_jobs(**<jobstore>) 删除所有定时任务
    10. scheduler.get_job(<id>,**<jobstore>) 获取job信息
    11. scheduler.modify_job(<id>,**<jobstore>, **kwargs) 修改job
    12. scheduler.pause_job(<id>, **<jobstore>) 暂停job
    13. scheduler.resume_job(<id>, **<jobstore>) 恢复job
    14. scheduler.run_job(<id>, **<jobstore>) 启动job
    15. scheduler.authenticate(<function>) 验证

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1033341.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

聊聊wireshark的进阶使用功能 | 京东云技术团队

1. 前言 emmm&#xff0c;说起网络知识学习肯定离不来wireshark工具&#xff0c;这个工具能够帮助我们快速地定位网络问题以及帮助正在学习网络协议这块的知识的同学验证理论与实际的一大利器&#xff0c;平时更多的只是停留在初步的使用阶段。也是利用部门内部的网络兴趣小组…

Webpack使用plugin插件自动在打包目录生成html文件

我们使用html-webpack-plugin插件可以自动在打包代码目录生成html文件 使用步骤&#xff1a; 一、安装依赖 在控制台中输入如下代码&#xff1a; npm i -D html-webpack-plugin 二、在webpack.config.js中配置插件 const HTMLPlugin require("html-webpack-plugin&q…

Activiz 9.2 for Linux Crack

Activiz 9.2 在 C#、.Net 和 Unity 软件中为您的 3D 内容释放可视化工具包的强大功能。 ActiViz 允许您轻松地将 3D 可视化集成到您的应用程序中。 ActiViz 功能 用 C# 封装的 3D 可视化软件系统 允许在 .NET 环境中快速开发可投入生产的交互式3D 应用程序 支持窗口演示基础 (…

VS2015没有“Win32控制台应用程序”模块

发现问题 成功安装VS2015专业版之后&#xff08;安装期间遇到“安装包缺失或损坏的问题”&#xff0c;参考安装VS2015时提示“安装包丢失或损坏”成功解决&#xff09;&#xff0c;由于它没有在桌面创建快捷方式&#xff0c;于是我在“开始”处找到与VS2015有关的图标&#xf…

设置github的默认分支

设置github的默认分支 更换默认分支默认分支的作用 更换默认分支 之前默认的分支想main, 现在想更换默认的分支 点击main, 可以看到有两个分支: main和gpuVersion, 可以看到这里默认main分支为default 如果想设置gpuVersion作为default,可以点击View all branches, 进入下一个…

【校招VIP】前端计算机网络之HTTP和HTTPS

考点介绍&#xff1a; 为了解决HTTP协议的缺陷&#xff0c;需要使用另一种协议&#xff1a;安全套接字层超文本传输协议HTTPS&#xff0c;为了数据传输的安全&#xff0c;HTTPS在HTTP的基础上加入了SSL/TLS协议&#xff0c;SSL/TLS依靠证书来验证服务器的身份&#xff0c;并为浏…

流媒体及直播相关知识

文章目录 前言一、流媒体1、基本概念2、流式传输3、流媒体技术原理4、流媒体传输模式5、H.264 流媒体传输系统框架 二、直播1、直播中使用的流媒体协议2、直播的模块划分3、视频直播流程①、推流到服务器②、服务器流分发 前言 本文主要讲解流媒体及其直播相关知识&#xff0c…

Linux 线程属性相关函数

pthread_attr_t就是对应线程的属性 /*#include <pthread.h>int pthread_attr_init(pthread_attr_t *attr);初始化线程属性变量int pthread_attr_destroy(pthread_attr_t *attr);释放线程属性资源int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *deta…

无人机“长坡”上,谁是滚出“厚雪球”的长期主义者?

“股神”巴菲特&#xff0c;曾提出过“长坡厚雪”的理论&#xff1a; 人生就像滚雪球&#xff0c;重要的是发现很湿的雪和很长的坡。 运用到企业经营上&#xff0c;“长坡”指的是企业所布局的领域发展潜力足、空间大&#xff1b;而“湿雪”&#xff0c;指的是企业竞争力强、…

Flowable主要子流程介绍

1. 内嵌子流程 &#xff08;1&#xff09;说明 内嵌子流程又叫嵌入式子流程&#xff0c;它是一个可以包含其它活动、分支、事件&#xff0c;等的活动。我们通常意义上说的子流程通常就是指的内嵌子流程&#xff0c;它表现为将一个流程&#xff08;子流程&#xff09;定…

发送实时音频数据到udp服务

由于浏览器不能直接连接udp服务&#xff0c;所以需要搭建一个websocket服务做中转&#xff0c;让websocket服务连接udp服务 1、vue开发获取实时音频数据并按4096分包后添加rtp协议头发送到websocket服务&#xff08;连接websocket自行编写连接到127.0.0.1:8889&#xff09; da…

代码随想录算法训练营 动态规划part06

一、完全背包 卡哥的总结&#xff0c;还挺全代码随想录 (programmercarl.com) 二、零钱兑换 II 518. 零钱兑换 II - 力扣&#xff08;LeetCode&#xff09; 被选物品之间不需要满足特定关系&#xff0c;只需要选择物品&#xff0c;以达到「全局最优」或者「特定状态」即可。 …

uni-app, 实现 scroll-view 自动滚动到底部,并控制触发频率

实现思路 通过 scroll-view 组件的 scroll-top 属性可以设置容器竖向滚动条位置 属性名Valuescroll-y允许纵向滚动scroll-top设置竖向滚动条位置 想要实现 scroll-view 滚动到底部&#xff0c;只需要让 scroll-top scroll-view 内容高度 - scroll-view 容器本身高度&#…

vuejs - - - - - 使用code编辑器codemirror

使用code编辑器codemirror 0. 效果图1. 依赖安装2. 组件封装3. 组件使用 0. 效果图 列表实现参考: 列表实现代码 1. 依赖安装 npm install codemirror codemirror-editor-vue3 jsonlint-mod 2. 组件封装 code-mirror-editor.vue <template><VueCodeMirrorclas…

蓝桥杯 题库 简单 每日十题 day8

01 扫雷 题目描述 在一个n行列的方格图上有一些位置有地雷&#xff0c;另外一些位置为空。 请为每个空位置标一个整数&#xff0c;表示周围八个相邻的方格中有多少个地雷。 输入描述 输入的第一行包含两个整数n&#xff0c;m。 第2行到第n1行每行包含m个整数&#xff0c;相邻整…

Smart UI Web 16.0.1 WebComponents htmlelements Crack

Javascript Web 组件库 Smart UI Web 组件库是您构建令人惊叹的 Web 应用程序所需的唯一套件。它包含 70 多个快速且专业设计的 UI 组件&#xff0c;可在单个包中实现美观且始终现代的 Web 应用程序。 具有高级功能的即用型Javascript 组件。只需几行代码即可使用数据网格、甘特…

Mybatis分页框架-PageHelper

Mybatis分页框架-PageHelper 一、PageHelper基础使用1.引入jar包2.配置conifg3.测试使用 二、PageHelper的多种用法1.使用PageHelper.startPage传入对象2.不使用PageHelper.startPage,而使用PageHelper.offsetPage3.使用Lambda进行分页4.不使用PageHelper直接分页5.想要使用分页…

代码随想录算法训练营 动态规划part17

一、回文子串 647. 回文子串 - 力扣&#xff08;LeetCode&#xff09; class Solution {public int countSubstrings(String s) {boolean[][] dp new boolean[s.length()][s.length()];int ans 0;for (int j 0; j < s.length(); j) {for (int i 0; i < j; i) {if …

5+铁死亡+分型+WGCNA+机器学习分析

今天给同学们分享一篇铁死亡分型WGCNA机器学习的生信文章“Identification of ferroptosis-related molecular clusters and genes for diabetic osteoporosis based on the machine learning”&#xff0c;这篇文章于2023年8月14日发表在Front Endocrinol (Lausanne)期刊上&am…

Nginx location 精准匹配URL = /

Location是什么&#xff1f; Location是Nginx中的块级指令(block directive)&#xff0c;通过配置Location指令块&#xff0c;可以决定客户端发过来的请求URI如何处理&#xff08;是映射到本地文件还是转发出去&#xff09;及被哪个location处理。 匹配模式 分为两种模式&…