首页 > 数据库 >python自定义装饰器,实现轮询监控数据库,并且根据字段内容变更打印相应日志或结束循环

python自定义装饰器,实现轮询监控数据库,并且根据字段内容变更打印相应日志或结束循环

时间:2024-01-29 22:34:06浏览次数:23  
标签:name 自定义 python 轮询 value current field values time

使用方法

可以写个while True的循环监控数据,再分别定义每个状态要做什么事情

注意:

  1. 循环中不要写breake
  2. 不要return, 换成yield, 把函数作为一个生成器,由装饰器控制循环

代码示例

import functools
import time

from utils.log_setting import logger
from config import settings


def monitorDB(field_name, continue_values=[], stop_values=[]):
    '''
    监听函数返回值,与stop_flags相等时结束监听
    field_name: 字段名,只用于打印
    continue_values: 非列表中的返回值跳出循环
    stop_value: 与被装饰函数返回值相等时跳出循环结束监听
    '''

    def decorator(func):
        # 使用装饰器语法,将装饰器应用到函数上
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            previous_value = None
            retry_wait_time = settings.MONITORDB.CONFIG.RETRY_WAIT_TIME  # 重试等待时间
            retry_count = settings.MONITORDB.CONFIG.RETRY_COUNT  # 最大重试次数
            run_count = 1  # 运行次数
            time_sleep_list = list(range(retry_wait_time, retry_wait_time * (retry_count + 1), retry_wait_time))
            time_start = time.perf_counter()
            try:
                time.sleep(0.5)
                # 获取最新的字段值
                time.sleep(1)
                current_value = next(func(*args, **kwargs))
            except StopIteration:
                logger.warning(f"{func.__name__}, 返回数据为空")
            while True:
                time.sleep(0.2)
                # 判断装饰器参数完整性
                if stop_values is [] and continue_values is []:
                    logger.error("{func.__name__}, 装饰器参数缺失")
                    break
                # 判断是否是列表中的返回值
                elif continue_values is not [] and current_value not in continue_values:
                    # 判断第一次执行
                    if previous_value is not None:
                        logger.info(f"{func.__name__}, {field_name} 从 {previous_value} 变为 {current_value}, done")
                    else:
                        logger.info(f"{func.__name__}, {field_name}: {current_value}")
                    break
                # 判断停止循环
                elif stop_values is not [] and current_value in stop_values:
                    # 判断第一次执行
                    if previous_value is not None:
                        logger.info(f"{func.__name__}, {field_name} 从 {previous_value} 变为 {current_value}, done")
                    else:
                        logger.info(f"{func.__name__}, {field_name}: {current_value}")
                    break
                elif current_value != previous_value:
                    time_start = time.perf_counter()
                    # 判断第一次执行
                    if previous_value is not None:
                        logger.info(f"{func.__name__}, {field_name} 从 {previous_value} 变为 {current_value}")
                    previous_value = current_value
                    retry_wait_time = settings.MONITORDB.CONFIG.RETRY_WAIT_TIME  # 重试等待时间
                    run_count = 1  # 运行次数
                    time_sleep_list = list(range(0, retry_wait_time * (retry_count + 1), retry_wait_time))
                elif current_value == previous_value:
                    time_run = time.perf_counter() - time_start
                    time_run_fmt = '{:.2f}s'.format(time_run)
                    print(
                        '\r***************************************************************************等待中{:.2f}s***************************************************************************'.format(time_run),
                        end="",
                    )
                    if time_run > retry_wait_time:
                        print('')
                        try:
                            logger.info(f"已等待{time_run_fmt}秒, {field_name}: {current_value}, 第{run_count}次重试...")
                            current_value = next(func(*args, **kwargs))
                            run_count += 1
                            retry_wait_time = time_sleep_list.pop(1)
                        except IndexError:
                            logger.warning(f"已等待{time_run_fmt}秒, {field_name}: {current_value}, 第{run_count}次重试失败, 不再重试")
                            break
                else:
                    logger.warning(f"{func.__name__}, 预料之外的参数field_name: {field_name}, continue_values: {continue_values}, stop_values: {stop_values}, current_value: {current_value}, previous_value: {previous_value}")
                time.sleep(0.2)

        return wrapper

    return decorator


if __name__ == '__main__':

    @monitorDB('IftttRuleTaskDetail_state', continue_values=[1, 2, 3, 4], stop_values=[4])
    def check_field_value():  # 模拟获取字段的当前值,可以替换为实际的代码
        while True:
            current_value = 0
            time.sleep(1)
            logger.info("程序运行中...")
            current_value = int(input('输入: '))
            yield current_value

    check_field_value()

标签:name,自定义,python,轮询,value,current,field,values,time
From: https://www.cnblogs.com/ishuangjin/p/17995511

相关文章

  • Python中的函数用法
    ​ Python中,函数是组织好的、可重用的、用来执行一个特定任务的代码块。函数提高了代码的模块化和代码重用率。函数是一种将代码块组织在一起以便重复使用的工具。函数可以接受输入数据,并返回输出数据。参考文档:Python中的函数用法-CJavaPy1、定义函数使用关键字def来定义......
  • sqlalchemy模块——python的ORM数据库
    介绍ORM数据库,简单理解就是把数据库的表抽象成一个个类,对数据库进行增删改查的时候可以直接通过库中的属性进行访问,即用python抽象数据库,通过sqlalchemy自动转换成数据库sql语句执行,可以更专注于代码的实现,可以配合sqlacodegen直接映射已有的数据库表,实际操作的时候需要借助其他......
  • shelve模块——python内置关系型数据库
    介绍python内置的关系型数据库,key-value的方式进行存储,使用的时候可以像字典一样调用,一般数据需要持久化的时候会用到此数据库,比如测试环境的一些基本不会更改的配置信息,可以使用shelve库存储,后续调用的时候不必每次都从接口拉取使用导入importshelve写入#writeback参数......
  • redis模块——python操作redis
    介绍使用python操作redis库中的缓存,常见操作,测试后清除测试数据缓存,测试前清理缓存保证不被之前的测试数据影响到测试准确性使用安装pipinstallredis导入importredis模糊搜索查找keymsp_fc_rule=self.msp_redis.keys('msp-cache-frequency-limit-info:*')循环遍历k......
  • 安装dmPython
    一、安装dmPython对于达梦数据库,必须首先安装dmPython,才可以使用,在$DM_HOME/drivers目录下有多种类型的驱动:[dmdba@dm8~]$cd/dm/dmdbms/drivers/[dmdba@dm8drivers]$lsdcidotNetdpifldrgojdbclogmnrmsgparseodbcphp_pdopythonr2dbc[dmdba@dm8......
  • 在内网(不通公网)的情况下,使用pip安装python依赖包
    1.施工服务器后端部署一:准备一台环境与内网虚拟机相同的可以连接外网的虚拟机,python版本,操作系统版本保持一致二:在可以链接外网的机器上使用pip将依赖包的whl文件(也有可能是tar.gz或者tar格式,不过不影响后续使用)#将依赖下载到本地的某个文件中root@iZ8v2rbZ:/sdwork/pyyl#......
  • Django - admin 表单编辑页面,增加自定义功能,前端上传视频到oss
    #背景:可以在admin编辑页面原有基础上,增加一些可定制的功能,如:在本地上传图片到oss,减少服务器的带宽压力,下面就以此为例。示例图:  一。models.py#video可以直接用字符串存储,因为最终里面只有有一串oss的视频路径classNews(models.Model):OSS_URL='https://xxxx......
  • python操作yaml
     补充:yaml语法详见:yaml语法 yaml应用场景1、保存测试数据2、也可以保存自动化测试中的关联数据  安装yaml模块pipinstallpyyaml==5.4.1 读取yaml数据读取数据:load()或者full_load(),返回一个对象用例数据:case.yaml-caseId:1apiName:registerdescr......
  • python 14
    1.代码规范程序员写代码四有规范的,不只是实现功能而已。1.1名称在python开发过程中会创建文件夹/文件/变量等,这些在命名有一些潜规则(编写代码时也要注意pep8规范)文件夹,小写&小写下划线连接,例如:commands,data_utils等。文件,小写&小写下划线连接,例如:page.py,db_convert.p......
  • C# 使用自定义特性标注类的方法,直接在当前类中让Main函数调用它
    有的时候我们想要再Main执行一些代码,如果直接在里面写的话,下次再想用的时候就会把之前的代码删掉,好不容易写的代码不想删掉于是我们可以将这些代码写到类文件中,想要执行了,就在Main中调用该类的方法,但是有的时候我们又懒的去Main函数指定的,有没有什么办法能直接在新类中就能指定......